source: trunk/tools/vslol/CppKeywordClassifier.cs @ 2122

Last change on this file since 2122 was 2122, checked in by sam, 8 years ago

vslol: only apply our syntax highlighting to keywords and identifiers
and update the version of the extension for publishing.

File size: 6.2 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel.Composition;
4using System.Windows.Media;
5using System.Text.RegularExpressions;
6
7using Microsoft.VisualStudio.Text;
8using Microsoft.VisualStudio.Text.Classification;
9using Microsoft.VisualStudio.Text.Formatting;
10using Microsoft.VisualStudio.Language.StandardClassification;
11using Microsoft.VisualStudio.Utilities;
12
13namespace Lol.VisualStudio.Plugin
14{
15    [Export(typeof(IClassifierProvider))]
16    [ContentType("c/c++")]
17    [ContentType("csharp")]
18    [ContentType("lolfx")]
19    internal class LolClassifierProvider : IClassifierProvider
20    {
21        [Import]
22        internal IClassificationTypeRegistryService m_type_registry = null; /* Set via MEF */
23        [Import]
24        internal IClassifierAggregatorService m_aggregator = null;
25        [Import]
26        internal IClassificationFormatMapService m_format_map = null;
27
28        internal static bool m_inprogress = false;
29
30        public IClassifier GetClassifier(ITextBuffer buffer)
31        {
32            /* Avoid infinite recursion */
33            if (m_inprogress)
34                return null;
35
36            LolGenericFormat.SetRegistry(m_type_registry, m_format_map);
37
38            try
39            {
40                m_inprogress = true;
41                return buffer.Properties.GetOrCreateSingletonProperty<CppKeywordClassifier>(delegate { return new CppKeywordClassifier(m_type_registry, m_aggregator.GetClassifier(buffer), buffer.ContentType); });
42            }
43            finally { m_inprogress = false; }
44        }
45    }
46
47    class CppKeywordClassifier : IClassifier
48    {
49        private IClassifier m_classifier;
50
51        private IClassificationType m_customclass_type;
52        private Regex m_customclass_regex;
53
54        internal CppKeywordClassifier(IClassificationTypeRegistryService registry,
55                                      IClassifier classifier,
56                                      IContentType type)
57        {
58            m_classifier = classifier;
59
60            m_customclass_type = registry.GetClassificationType("LolCustomClass");
61
62            string tmp = @"\b(";
63            tmp += "void|bool|int|unsigned|char|short|long|float|double|ldouble|";
64            tmp += "class|struct|union|template|const|static|extern|volatile|inline|namespace|";
65            if (type.IsOfType("lolfx"))
66                tmp += "attribute|varying|uniform|in|out|";
67            if (type.IsOfType("csharp"))
68                tmp += "var|string|internal|sealed|public|private|protected|";
69            if (!type.IsOfType("csharp"))
70                tmp += "(f(16|128)||d|[ui](8|16||64)|r)(vec[234]|mat[234]|quat|cmplx)|";
71            if (type.IsOfType("c/c++"))
72            {
73                tmp += "u?int(8|16|32|64|ptr)_t|";
74                tmp += "real|half|explicit|typename|typedef|";
75            }
76            tmp = tmp.Remove(tmp.Length - 1);
77            tmp += @")\b";
78            m_customclass_regex = new Regex(tmp);
79        }
80
81        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
82        {
83            List<ClassificationSpan> ret = new List<ClassificationSpan>();
84
85            foreach (ClassificationSpan cs in m_classifier.GetClassificationSpans(span))
86            {
87                string cs_class = cs.ClassificationType.Classification.ToLower();
88
89                /* Only apply our rules if we found a keyword or an identifier */
90                if (cs_class == "keyword" || cs_class == "identifier")
91                {
92                    if (m_customclass_regex.IsMatch(cs.Span.GetText()))
93                    {
94                        ret.Add(new ClassificationSpan(cs.Span, m_customclass_type));
95                        continue;
96                    }
97                }
98
99                ret.Add(cs);
100            }
101
102            return ret;
103        }
104
105        public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
106    }
107
108    internal class LolGenericFormat : ClassificationFormatDefinition
109    {
110        static IClassificationTypeRegistryService m_type_registry;
111        static IClassificationFormatMapService m_format_map;
112
113        public static void SetRegistry(IClassificationTypeRegistryService type_registry,
114                                       IClassificationFormatMapService format_map)
115        {
116            m_type_registry = type_registry;
117            m_format_map = format_map;
118        }
119
120        protected void CopyStyleColor(string category)
121        {
122            if (m_type_registry == null || m_format_map == null)
123                return;
124
125            var map = m_format_map.GetClassificationFormatMap("Text Editor");
126            if (map == null)
127                return;
128
129            //string[] foo = { "Comment", "Keyword", "C/C++ User Keywords", "Call Return", "HTML Comment" , "User Types", "User Types (Type parameters)", "User Types (Value types)"};
130
131            var type = m_type_registry.GetClassificationType(category);
132            if (type == null)
133                return;
134
135            var prop = map.GetExplicitTextProperties(type);
136            if (prop == null)
137                return;
138
139            var c1 = prop.ForegroundBrush as SolidColorBrush;
140            if (c1 != null && c1.Color != Colors.Transparent)
141                this.ForegroundColor = c1.Color;
142            var c2 = prop.BackgroundBrush as SolidColorBrush;
143            if (c2 != null && c2.Color != Colors.Transparent)
144                this.BackgroundColor = c1.Color;
145        }
146    }
147
148    internal static class LolClassifierClassificationDefinition
149    {
150        [Export(typeof(ClassificationTypeDefinition))]
151        [Name(LolCppTypeFormat.m_name)]
152        internal static ClassificationTypeDefinition LolCustomClassType = null;
153    }
154
155    [Export(typeof(EditorFormatDefinition))]
156    [ClassificationType(ClassificationTypeNames = LolCppTypeFormat.m_name)]
157    [Name(LolCppTypeFormat.m_name)]
158    [UserVisible(true)]
159    [Order(After = Priority.Default)] /* Override the Visual Studio classifiers */
160    internal sealed class LolCppTypeFormat : LolGenericFormat
161    {
162        public const string m_name = "LolCustomClass";
163        public LolCppTypeFormat()
164        {
165            this.DisplayName = "C/C++ Types and Qualifiers";
166            this.ForegroundColor = Colors.Lime;
167            this.IsBold = true;
168            //CopyStyleColor("User Types");
169        }
170    }
171}
Note: See TracBrowser for help on using the repository browser.