From 6f3e1f87dea7d45adf5b6940902278d3064403e2 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 13 Jan 2010 13:56:56 +0000 Subject: [PATCH] Improve XML highlighting. Fixed bug in XSHD loader when XSHD refers to a ruleset defined later in the same file. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5398 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Highlighting/Resources/Resources.cs | 1 + .../Highlighting/Resources/XML-Mode.xshd | 48 ++++++++++++------ .../Xshd/XmlHighlightingDefinition.cs | 50 +++++++++++++------ 3 files changed, 71 insertions(+), 28 deletions(-) diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/Resources.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/Resources.cs index 4dbda992ee..b926198320 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/Resources.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/Resources.cs @@ -31,6 +31,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting hlm.RegisterHighlighting("HTML", new[] { ".htm", ".html" }, "HTML-Mode.xshd"); hlm.RegisterHighlighting("ASP/XHTML", new[] { ".asp", ".aspx", ".asax", ".asmx" }, "ASPX.xshd"); + //hlm.RegisterHighlighting("Batch", new[] { ".bat", ".cmd" }, "BAT-Mode.xshd"); hlm.RegisterHighlighting("Boo", new[] { ".boo" }, "Boo.xshd"); hlm.RegisterHighlighting("Coco", new[] { ".atg" }, "Coco-Mode.xshd"); hlm.RegisterHighlighting("C++", new[] { ".c", ".h", ".cc", ".cpp" , ".hpp" }, "CPP-Mode.xshd"); diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/XML-Mode.xshd b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/XML-Mode.xshd index 79ce161f54..bfdfeb6407 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/XML-Mode.xshd +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/XML-Mode.xshd @@ -1,41 +1,61 @@ + + + + + + + + + + - + <!-- --> - + <!\[CDATA\[ ]]> - + <!DOCTYPE > - + <\? \?> - + < > - + " " - + ' ' - [\d\w_\-\.]+(?=(\s*=)) - = - / + [\d\w_\-\.]+(?=(\s*=)) + = - - & - ; - + + + + + + & + [\w\d\#]+ + ; + + + + & + [\w\d\#]* + #missing ; + \ No newline at end of file diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/XmlHighlightingDefinition.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/XmlHighlightingDefinition.cs index 24c414b192..4a4e86071a 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/XmlHighlightingDefinition.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/XmlHighlightingDefinition.cs @@ -24,8 +24,9 @@ namespace ICSharpCode.AvalonEdit.Highlighting.Xshd public XmlHighlightingDefinition(XshdSyntaxDefinition xshd, IHighlightingDefinitionReferenceResolver resolver) { this.Name = xshd.Name; - xshd.AcceptElements(new RegisterNamedElementsVisitor(this)); - TranslateElementVisitor translateVisitor = new TranslateElementVisitor(this, resolver); + var rnev = new RegisterNamedElementsVisitor(this); + xshd.AcceptElements(rnev); + TranslateElementVisitor translateVisitor = new TranslateElementVisitor(this, rnev.ruleSets, resolver); foreach (XshdElement element in xshd.Elements) { HighlightingRuleSet rs = element.AcceptVisitor(translateVisitor) as HighlightingRuleSet; XshdRuleSet xrs = element as XshdRuleSet; @@ -44,6 +45,8 @@ namespace ICSharpCode.AvalonEdit.Highlighting.Xshd sealed class RegisterNamedElementsVisitor : IXshdVisitor { XmlHighlightingDefinition def; + internal readonly Dictionary ruleSets + = new Dictionary(); public RegisterNamedElementsVisitor(XmlHighlightingDefinition def) { @@ -52,13 +55,15 @@ namespace ICSharpCode.AvalonEdit.Highlighting.Xshd public object VisitRuleSet(XshdRuleSet ruleSet) { + HighlightingRuleSet hrs = new HighlightingRuleSet(); + ruleSets.Add(ruleSet, hrs); if (ruleSet.Name != null) { if (ruleSet.Name.Length == 0) throw Error(ruleSet, "Name must not be the empty string"); if (def.ruleSetDict.ContainsKey(ruleSet.Name)) throw Error(ruleSet, "Duplicate rule set name '" + ruleSet.Name + "'."); - def.ruleSetDict.Add(ruleSet.Name, new HighlightingRuleSet()); + def.ruleSetDict.Add(ruleSet.Name, hrs); } ruleSet.AcceptElements(this); return null; @@ -105,25 +110,34 @@ namespace ICSharpCode.AvalonEdit.Highlighting.Xshd #region TranslateElements sealed class TranslateElementVisitor : IXshdVisitor { - XmlHighlightingDefinition def; - IHighlightingDefinitionReferenceResolver resolver; + readonly XmlHighlightingDefinition def; + readonly Dictionary ruleSetDict; + readonly Dictionary reverseRuleSetDict; + readonly IHighlightingDefinitionReferenceResolver resolver; + HashSet processingStartedRuleSets = new HashSet(); + HashSet processedRuleSets = new HashSet(); + bool ignoreCase; - public TranslateElementVisitor(XmlHighlightingDefinition def, IHighlightingDefinitionReferenceResolver resolver) + public TranslateElementVisitor(XmlHighlightingDefinition def, Dictionary ruleSetDict, IHighlightingDefinitionReferenceResolver resolver) { Debug.Assert(def != null); + Debug.Assert(ruleSetDict != null); this.def = def; + this.ruleSetDict = ruleSetDict; this.resolver = resolver; + reverseRuleSetDict = new Dictionary(); + foreach (var pair in ruleSetDict) { + reverseRuleSetDict.Add(pair.Value, pair.Key); + } } - bool ignoreCase; - public object VisitRuleSet(XshdRuleSet ruleSet) { - HighlightingRuleSet rs; - if (ruleSet.Name != null) - rs = def.ruleSetDict[ruleSet.Name]; - else - rs = new HighlightingRuleSet(); + HighlightingRuleSet rs = ruleSetDict[ruleSet]; + if (processedRuleSets.Contains(ruleSet)) + return rs; + if (!processingStartedRuleSets.Add(ruleSet)) + throw Error(ruleSet, "RuleSet cannot be processed because it contains cyclic "); bool oldIgnoreCase = ignoreCase; if (ruleSet.IgnoreCase != null) @@ -150,6 +164,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting.Xshd } ignoreCase = oldIgnoreCase; + processedRuleSets.Add(ruleSet); return rs; } @@ -301,7 +316,14 @@ namespace ICSharpCode.AvalonEdit.Highlighting.Xshd public object VisitImport(XshdImport import) { - return GetRuleSet(import, import.RuleSetReference); + HighlightingRuleSet hrs = GetRuleSet(import, import.RuleSetReference); + XshdRuleSet inputRuleSet; + if (reverseRuleSetDict.TryGetValue(hrs, out inputRuleSet)) { + // ensure the ruleset is processed before importing its members + if (VisitRuleSet(inputRuleSet) != hrs) + Debug.Fail("this shouldn't happen"); + } + return hrs; } public object VisitRule(XshdRule rule)