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

Last change on this file since 2123 was 2123, checked in by sam, 7 years ago

vslol: add licensing information to important files.

File size: 7.9 KB
Line 
1//
2// Lol Engine - VsLol add-in for Visual Studio
3//
4// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://www.wtfpl.net/ for more details.
9//
10
11using System;
12using System.Collections.Generic;
13using System.ComponentModel.Composition;
14using System.Windows.Media;
15using System.Text.RegularExpressions;
16
17using Microsoft.VisualStudio.Text;
18using Microsoft.VisualStudio.Text.Classification;
19using Microsoft.VisualStudio.Text.Formatting;
20using Microsoft.VisualStudio.Language.StandardClassification;
21using Microsoft.VisualStudio.Utilities;
22
23namespace lol
24{
25
26[Export(typeof(IClassifierProvider))]
27[ContentType("c/c++")]
28[ContentType("csharp")]
29[ContentType("lolfx")]
30internal class LolClassifierProvider : IClassifierProvider
31{
32    [Import]
33    internal IClassificationTypeRegistryService m_type_registry = null; /* Set via MEF */
34    [Import]
35    internal IClassifierAggregatorService m_aggregator = null;
36    [Import]
37    internal IClassificationFormatMapService m_format_map = null;
38
39    internal static bool m_inprogress = false;
40
41    public IClassifier GetClassifier(ITextBuffer buffer)
42    {
43        /* Avoid infinite recursion */
44        if (m_inprogress)
45            return null;
46
47        LolGenericFormat.SetRegistry(m_type_registry, m_format_map);
48
49        try
50        {
51            m_inprogress = true;
52            return buffer.Properties.GetOrCreateSingletonProperty<CppKeywordClassifier>(delegate { return new CppKeywordClassifier(m_type_registry, m_aggregator.GetClassifier(buffer), buffer.ContentType); });
53        }
54        finally { m_inprogress = false; }
55    }
56}
57
58class CppKeywordClassifier : IClassifier
59{
60    private IClassifier m_classifier;
61
62    private IClassificationType m_customclass_type, m_constant_type;
63    private Regex m_customclass_regex, m_constant_regex;
64
65    internal CppKeywordClassifier(IClassificationTypeRegistryService registry,
66                                  IClassifier classifier,
67                                  IContentType type)
68    {
69        m_classifier = classifier;
70
71        /* Regex for types and specifiers */
72        m_customclass_type = registry.GetClassificationType("LolCustomClass");
73
74        string tmp = @"\b(";
75        tmp += "void|bool|int|unsigned|char|short|long|float|double|ldouble|";
76        tmp += "class|struct|union|template|const|static|extern|volatile|inline|namespace|";
77        if (type.IsOfType("lolfx"))
78            tmp += "attribute|varying|uniform|in|out|";
79        if (type.IsOfType("csharp"))
80            tmp += "var|out|ref|string|internal|sealed|public|private|protected|override|";
81        if (!type.IsOfType("csharp"))
82            tmp += "(f(16|128)||d|[ui](8|16||64)|r)(vec[234]|mat[234]|quat|cmplx)|";
83        if (type.IsOfType("c/c++"))
84        {
85            tmp += "u?int(8|16|32|64|ptr)_t|";
86            tmp += "(wchar|size|ssize)_t|";
87            tmp += "real|half|explicit|typename|typedef|auto|";
88        }
89        tmp = tmp.Remove(tmp.Length - 1);
90        tmp += @")\b";
91        m_customclass_regex = new Regex(tmp);
92
93        /* Regex for constant words */
94        m_constant_type = registry.GetClassificationType("LolCppConstant");
95
96        if (type.IsOfType("csharp"))
97            m_constant_regex = new Regex(@"\b(null|true|false)\b");
98        else if (type.IsOfType("c/c++"))
99            m_constant_regex = new Regex(@"\b(NULL|nullptr|true|false|M_PI)\b");
100        else if (type.IsOfType("lolfx"))
101            m_constant_regex = new Regex(@"\b(gl_Position|gl_FragColor)\b");
102        else
103            m_constant_regex = new Regex(@"\b(NULL)\b");
104
105    }
106
107    public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
108    {
109        List<ClassificationSpan> ret = new List<ClassificationSpan>();
110
111        foreach (ClassificationSpan cs in m_classifier.GetClassificationSpans(span))
112        {
113            string cs_class = cs.ClassificationType.Classification.ToLower();
114
115            /* Only apply our rules if we found a keyword or an identifier */
116            if (cs_class == "keyword" || cs_class == "identifier")
117            {
118                if (m_customclass_regex.IsMatch(cs.Span.GetText()))
119                {
120                    ret.Add(new ClassificationSpan(cs.Span, m_customclass_type));
121                    continue;
122                }
123
124                if (m_constant_regex.IsMatch(cs.Span.GetText()))
125                {
126                    ret.Add(new ClassificationSpan(cs.Span, m_constant_type));
127                    continue;
128                }
129            }
130
131            ret.Add(cs);
132        }
133
134        return ret;
135    }
136
137    public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
138}
139
140internal class LolGenericFormat : ClassificationFormatDefinition
141{
142    static IClassificationTypeRegistryService m_type_registry;
143    static IClassificationFormatMapService m_format_map;
144
145    public static void SetRegistry(IClassificationTypeRegistryService type_registry,
146                                   IClassificationFormatMapService format_map)
147    {
148        m_type_registry = type_registry;
149        m_format_map = format_map;
150    }
151
152    protected void CopyStyleColor(string category)
153    {
154        if (m_type_registry == null || m_format_map == null)
155            return;
156
157        var map = m_format_map.GetClassificationFormatMap("Text Editor");
158        if (map == null)
159            return;
160
161        //string[] foo = { "Comment", "Keyword", "C/C++ User Keywords", "Call Return", "HTML Comment" , "User Types", "User Types (Type parameters)", "User Types (Value types)"};
162
163        var type = m_type_registry.GetClassificationType(category);
164        if (type == null)
165            return;
166
167        var prop = map.GetExplicitTextProperties(type);
168        if (prop == null)
169            return;
170
171        var c1 = prop.ForegroundBrush as SolidColorBrush;
172        if (c1 != null && c1.Color != Colors.Transparent)
173        {
174            this.ForegroundColor = c1.Color;
175            this.ForegroundOpacity = 1.0;
176        }
177        var c2 = prop.BackgroundBrush as SolidColorBrush;
178        if (c2 != null && c2.Color != Colors.Transparent)
179        {
180            this.BackgroundColor = c2.Color;
181            this.BackgroundOpacity = 1.0;
182        }
183    }
184}
185
186internal static class LolClassifierClassificationDefinition
187{
188    [Export(typeof(ClassificationTypeDefinition))]
189    [Name(LolCppTypeFormat.m_name)]
190    internal static ClassificationTypeDefinition LolCustomClassType = null;
191
192    [Export(typeof(ClassificationTypeDefinition))]
193    [Name(LolCppConstantFormat.m_name)]
194    internal static ClassificationTypeDefinition LolCustomConstantType = null;
195}
196
197[Export(typeof(EditorFormatDefinition))]
198[ClassificationType(ClassificationTypeNames = LolCppTypeFormat.m_name)]
199[Name(LolCppTypeFormat.m_name)]
200[UserVisible(true)]
201[Order(After = Priority.Default)] /* Override the Visual Studio classifiers */
202internal sealed class LolCppTypeFormat : LolGenericFormat
203{
204    public const string m_name = "LolCustomClass";
205    public LolCppTypeFormat()
206    {
207        this.DisplayName = "C/C++ Types and Qualifiers";
208        this.ForegroundColor = Colors.Lime;
209        this.ForegroundOpacity = 1.0;
210        this.IsBold = true;
211        //CopyStyleColor("User Types");
212    }
213}
214
215[Export(typeof(EditorFormatDefinition))]
216[ClassificationType(ClassificationTypeNames = LolCppConstantFormat.m_name)]
217[Name(LolCppConstantFormat.m_name)]
218[UserVisible(true)]
219[Order(After = Priority.Default)] /* Override the Visual Studio classifiers */
220internal sealed class LolCppConstantFormat : LolGenericFormat
221{
222    public const string m_name = "LolCppConstant";
223    public LolCppConstantFormat()
224    {
225        this.DisplayName = "C/C++ Constants";
226        this.ForegroundColor = Colors.Magenta;
227        this.ForegroundOpacity = 1.0;
228        this.IsBold = true;
229        //CopyStyleColor("User Types");
230    }
231}
232
233} /* namespace lol */
Note: See TracBrowser for help on using the repository browser.