Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.AvalonEdit/5.0.1/AvalonEdit-5.0.1/Highlighting/Xshd/V2Loader.cs @ 11700

Last change on this file since 11700 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 11.6 KB
Line 
1// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Collections.Generic;
21using System.Diagnostics;
22using System.Windows;
23using System.Windows.Media;
24using System.Xml;
25using System.Xml.Schema;
26
27using ICSharpCode.AvalonEdit.Utils;
28
29namespace ICSharpCode.AvalonEdit.Highlighting.Xshd
30{
31  /// <summary>
32  /// Loads .xshd files, version 2.0.
33  /// Version 2.0 files are recognized by the namespace.
34  /// </summary>
35  static class V2Loader
36  {
37    public const string Namespace = "http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008";
38   
39    static XmlSchemaSet schemaSet;
40   
41    static XmlSchemaSet SchemaSet {
42      get {
43        if (schemaSet == null) {
44          schemaSet = HighlightingLoader.LoadSchemaSet(new XmlTextReader(
45            Resources.OpenStream("ModeV2.xsd")));
46        }
47        return schemaSet;
48      }
49    }
50   
51    public static XshdSyntaxDefinition LoadDefinition(XmlReader reader, bool skipValidation)
52    {
53      reader = HighlightingLoader.GetValidatingReader(reader, true, skipValidation ? null : SchemaSet);
54      reader.Read();
55      return ParseDefinition(reader);
56    }
57   
58    static XshdSyntaxDefinition ParseDefinition(XmlReader reader)
59    {
60      Debug.Assert(reader.LocalName == "SyntaxDefinition");
61      XshdSyntaxDefinition def = new XshdSyntaxDefinition();
62      def.Name = reader.GetAttribute("name");
63      string extensions = reader.GetAttribute("extensions");
64      if (extensions != null)
65        def.Extensions.AddRange(extensions.Split(';'));
66      ParseElements(def.Elements, reader);
67      Debug.Assert(reader.NodeType == XmlNodeType.EndElement);
68      Debug.Assert(reader.LocalName == "SyntaxDefinition");
69      return def;
70    }
71   
72    static void ParseElements(ICollection<XshdElement> c, XmlReader reader)
73    {
74      if (reader.IsEmptyElement)
75        return;
76      while (reader.Read() && reader.NodeType != XmlNodeType.EndElement) {
77        Debug.Assert(reader.NodeType == XmlNodeType.Element);
78        if (reader.NamespaceURI != Namespace) {
79          if (!reader.IsEmptyElement)
80            reader.Skip();
81          continue;
82        }
83        switch (reader.Name) {
84          case "RuleSet":
85            c.Add(ParseRuleSet(reader));
86            break;
87          case "Property":
88            c.Add(ParseProperty(reader));
89            break;
90          case "Color":
91            c.Add(ParseNamedColor(reader));
92            break;
93          case "Keywords":
94            c.Add(ParseKeywords(reader));
95            break;
96          case "Span":
97            c.Add(ParseSpan(reader));
98            break;
99          case "Import":
100            c.Add(ParseImport(reader));
101            break;
102          case "Rule":
103            c.Add(ParseRule(reader));
104            break;
105          default:
106            throw new NotSupportedException("Unknown element " + reader.Name);
107        }
108      }
109    }
110   
111    static XshdElement ParseProperty(XmlReader reader)
112    {
113      XshdProperty property = new XshdProperty();
114      SetPosition(property, reader);
115      property.Name = reader.GetAttribute("name");
116      property.Value = reader.GetAttribute("value");
117      return property;
118    }
119   
120    static XshdRuleSet ParseRuleSet(XmlReader reader)
121    {
122      XshdRuleSet ruleSet = new XshdRuleSet();
123      SetPosition(ruleSet, reader);
124      ruleSet.Name = reader.GetAttribute("name");
125      ruleSet.IgnoreCase = reader.GetBoolAttribute("ignoreCase");
126     
127      CheckElementName(reader, ruleSet.Name);
128      ParseElements(ruleSet.Elements, reader);
129      return ruleSet;
130    }
131   
132    static XshdRule ParseRule(XmlReader reader)
133    {
134      XshdRule rule = new XshdRule();
135      SetPosition(rule, reader);
136      rule.ColorReference = ParseColorReference(reader);
137      if (!reader.IsEmptyElement) {
138        reader.Read();
139        if (reader.NodeType == XmlNodeType.Text) {
140          rule.Regex = reader.ReadContentAsString();
141          rule.RegexType = XshdRegexType.IgnorePatternWhitespace;
142        }
143      }
144      return rule;
145    }
146   
147    static XshdKeywords ParseKeywords(XmlReader reader)
148    {
149      XshdKeywords keywords = new XshdKeywords();
150      SetPosition(keywords, reader);
151      keywords.ColorReference = ParseColorReference(reader);
152      reader.Read();
153      while (reader.NodeType != XmlNodeType.EndElement) {
154        Debug.Assert(reader.NodeType == XmlNodeType.Element);
155        keywords.Words.Add(reader.ReadElementString());
156      }
157      return keywords;
158    }
159   
160    static XshdImport ParseImport(XmlReader reader)
161    {
162      XshdImport import = new XshdImport();
163      SetPosition(import, reader);
164      import.RuleSetReference = ParseRuleSetReference(reader);
165      if (!reader.IsEmptyElement)
166        reader.Skip();
167      return import;
168    }
169   
170    static XshdSpan ParseSpan(XmlReader reader)
171    {
172      XshdSpan span = new XshdSpan();
173      SetPosition(span, reader);
174      span.BeginRegex = reader.GetAttribute("begin");
175      span.EndRegex = reader.GetAttribute("end");
176      span.Multiline = reader.GetBoolAttribute("multiline") ?? false;
177      span.SpanColorReference = ParseColorReference(reader);
178      span.RuleSetReference = ParseRuleSetReference(reader);
179      if (!reader.IsEmptyElement) {
180        reader.Read();
181        while (reader.NodeType != XmlNodeType.EndElement) {
182          Debug.Assert(reader.NodeType == XmlNodeType.Element);
183          switch (reader.Name) {
184            case "Begin":
185              if (span.BeginRegex != null)
186                throw Error(reader, "Duplicate Begin regex");
187              span.BeginColorReference = ParseColorReference(reader);
188              span.BeginRegex = reader.ReadElementString();
189              span.BeginRegexType = XshdRegexType.IgnorePatternWhitespace;
190              break;
191            case "End":
192              if (span.EndRegex != null)
193                throw Error(reader, "Duplicate End regex");
194              span.EndColorReference = ParseColorReference(reader);
195              span.EndRegex = reader.ReadElementString();
196              span.EndRegexType = XshdRegexType.IgnorePatternWhitespace;
197              break;
198            case "RuleSet":
199              if (span.RuleSetReference.ReferencedElement != null)
200                throw Error(reader, "Cannot specify both inline RuleSet and RuleSet reference");
201              span.RuleSetReference = new XshdReference<XshdRuleSet>(ParseRuleSet(reader));
202              reader.Read();
203              break;
204            default:
205              throw new NotSupportedException("Unknown element " + reader.Name);
206          }
207        }
208      }
209      return span;
210    }
211   
212    static Exception Error(XmlReader reader, string message)
213    {
214      return Error(reader as IXmlLineInfo, message);
215    }
216   
217    static Exception Error(IXmlLineInfo lineInfo, string message)
218    {
219      if (lineInfo != null)
220        return new HighlightingDefinitionInvalidException(HighlightingLoader.FormatExceptionMessage(message, lineInfo.LineNumber, lineInfo.LinePosition));
221      else
222        return new HighlightingDefinitionInvalidException(message);
223    }
224   
225    /// <summary>
226    /// Sets the element's position to the XmlReader's position.
227    /// </summary>
228    static void SetPosition(XshdElement element, XmlReader reader)
229    {
230      IXmlLineInfo lineInfo = reader as IXmlLineInfo;
231      if (lineInfo != null) {
232        element.LineNumber = lineInfo.LineNumber;
233        element.ColumnNumber = lineInfo.LinePosition;
234      }
235    }
236   
237    static XshdReference<XshdRuleSet> ParseRuleSetReference(XmlReader reader)
238    {
239      string ruleSet = reader.GetAttribute("ruleSet");
240      if (ruleSet != null) {
241        // '/' is valid in highlighting definition names, so we need the last occurence
242        int pos = ruleSet.LastIndexOf('/');
243        if (pos >= 0) {
244          return new XshdReference<XshdRuleSet>(ruleSet.Substring(0, pos), ruleSet.Substring(pos + 1));
245        } else {
246          return new XshdReference<XshdRuleSet>(null, ruleSet);
247        }
248      } else {
249        return new XshdReference<XshdRuleSet>();
250      }
251    }
252   
253    static void CheckElementName(XmlReader reader, string name)
254    {
255      if (name != null) {
256        if (name.Length == 0)
257          throw Error(reader, "The empty string is not a valid name.");
258        if (name.IndexOf('/') >= 0)
259          throw Error(reader, "Element names must not contain a slash.");
260      }
261    }
262   
263    #region ParseColor
264    static XshdColor ParseNamedColor(XmlReader reader)
265    {
266      XshdColor color = ParseColorAttributes(reader);
267      // check removed: invisible named colors may be useful now that apps can read highlighting data
268      //if (color.Foreground == null && color.FontWeight == null && color.FontStyle == null)
269      //  throw Error(reader, "A named color must have at least one element.");
270      color.Name = reader.GetAttribute("name");
271      CheckElementName(reader, color.Name);
272      color.ExampleText = reader.GetAttribute("exampleText");
273      return color;
274    }
275   
276    static XshdReference<XshdColor> ParseColorReference(XmlReader reader)
277    {
278      string color = reader.GetAttribute("color");
279      if (color != null) {
280        int pos = color.LastIndexOf('/');
281        if (pos >= 0) {
282          return new XshdReference<XshdColor>(color.Substring(0, pos), color.Substring(pos + 1));
283        } else {
284          return new XshdReference<XshdColor>(null, color);
285        }
286      } else {
287        return new XshdReference<XshdColor>(ParseColorAttributes(reader));
288      }
289    }
290   
291    static XshdColor ParseColorAttributes(XmlReader reader)
292    {
293      XshdColor color = new XshdColor();
294      SetPosition(color, reader);
295      IXmlLineInfo position = reader as IXmlLineInfo;
296      color.Foreground = ParseColor(position, reader.GetAttribute("foreground"));
297      color.Background = ParseColor(position, reader.GetAttribute("background"));
298      color.FontWeight = ParseFontWeight(reader.GetAttribute("fontWeight"));
299      color.FontStyle = ParseFontStyle(reader.GetAttribute("fontStyle"));
300      return color;
301    }
302   
303    internal readonly static ColorConverter ColorConverter = new ColorConverter();
304    internal readonly static FontWeightConverter FontWeightConverter = new FontWeightConverter();
305    internal readonly static FontStyleConverter FontStyleConverter = new FontStyleConverter();
306   
307    static HighlightingBrush ParseColor(IXmlLineInfo lineInfo, string color)
308    {
309      if (string.IsNullOrEmpty(color))
310        return null;
311      if (color.StartsWith("SystemColors.", StringComparison.Ordinal))
312        return GetSystemColorBrush(lineInfo, color);
313      else
314        return FixedColorHighlightingBrush((Color?)ColorConverter.ConvertFromInvariantString(color));
315    }
316   
317    internal static SystemColorHighlightingBrush GetSystemColorBrush(IXmlLineInfo lineInfo, string name)
318    {
319      Debug.Assert(name.StartsWith("SystemColors.", StringComparison.Ordinal));
320      string shortName = name.Substring(13);
321      var property = typeof(SystemColors).GetProperty(shortName + "Brush");
322      if (property == null)
323        throw Error(lineInfo, "Cannot find '" + name + "'.");
324      return new SystemColorHighlightingBrush(property);
325    }
326   
327    static HighlightingBrush FixedColorHighlightingBrush(Color? color)
328    {
329      if (color == null)
330        return null;
331      return new SimpleHighlightingBrush(color.Value);
332    }
333   
334    static FontWeight? ParseFontWeight(string fontWeight)
335    {
336      if (string.IsNullOrEmpty(fontWeight))
337        return null;
338      return (FontWeight?)FontWeightConverter.ConvertFromInvariantString(fontWeight);
339    }
340   
341    static FontStyle? ParseFontStyle(string fontStyle)
342    {
343      if (string.IsNullOrEmpty(fontStyle))
344        return null;
345      return (FontStyle?)FontStyleConverter.ConvertFromInvariantString(fontStyle);
346    }
347    #endregion
348  }
349}
Note: See TracBrowser for help on using the repository browser.