main
cs 128 lines 3.88 KB
Raw
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 namespace WixToolset.Converters
4 {
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 using System.Xml.Linq;
9
10 internal class ConversionLab : IDisposable
11 {
12 private readonly XElement targetElement;
13 private readonly XElement parentElement;
14 private readonly List<XNode> siblingNodes;
15 private int index;
16
17 public ConversionLab(XElement targetElement)
18 {
19 this.targetElement = targetElement;
20 this.parentElement = this.targetElement.Parent;
21 this.siblingNodes = this.parentElement.Nodes().ToList();
22
23 foreach (var siblingNode in this.siblingNodes)
24 {
25 siblingNode.Remove();
26 }
27
28 this.index = this.siblingNodes.IndexOf(this.targetElement);
29 }
30
31 public void RemoveOrphanTextNodes()
32 {
33 if (!this.targetElement.HasElements)
34 {
35 var childNodes = this.targetElement.Nodes().ToList();
36 foreach (var childNode in childNodes)
37 {
38 childNode.Remove();
39 }
40 }
41 }
42
43 public void InsertElementBeforeTargetElement(XElement newElement)
44 {
45 var index = this.index - 1;
46
47 if (0 <= index
48 && this.siblingNodes[index] is XText leadingText
49 && String.IsNullOrWhiteSpace(leadingText.Value))
50 {
51 this.siblingNodes.Insert(index, newElement);
52 this.siblingNodes.Insert(index, new XText(leadingText.Value));
53 this.index += 2;
54 }
55 }
56
57 private bool IsUniqueElement(XElement newElement)
58 {
59 foreach (XNode node in this.siblingNodes)
60 {
61 if (node is XElement element)
62 {
63 if (element.Name == newElement.Name)
64 {
65 return false;
66 }
67 }
68 }
69
70 return true;
71 }
72
73 public void InsertUniqueElementBeforeTargetElement(XElement newElement)
74 {
75 if (this.IsUniqueElement(newElement))
76 {
77 this.InsertElementBeforeTargetElement(newElement);
78 }
79 }
80
81 public void RemoveTargetElement()
82 {
83 this.siblingNodes.RemoveAt(this.index);
84
85 var index = this.index - 1;
86
87 if (0 <= index
88 && this.siblingNodes[index] is XText leadingText
89 && String.IsNullOrWhiteSpace(leadingText.Value))
90 {
91 this.siblingNodes.RemoveAt(index);
92 }
93
94 this.RemoveOrphanTextNodes();
95 }
96
97 public void ReplaceTargetElement(XElement replacement)
98 {
99 this.siblingNodes[this.index] = replacement;
100 }
101
102 public void AddCommentsAsSiblings(List<XNode> comments)
103 {
104 if (0 < this.index
105 && this.siblingNodes[this.index - 1] is XText leadingText
106 && String.IsNullOrWhiteSpace(leadingText.Value))
107 {
108 var leadingWhitespace = leadingText.Value;
109 --this.index;
110 var newComments = new List<XNode>();
111 foreach(var comment in comments)
112 {
113 newComments.Add(new XText(leadingWhitespace));
114 newComments.Add(comment);
115 }
116 comments = newComments;
117 }
118
119 this.siblingNodes.InsertRange(this.index, comments);
120 this.index = this.siblingNodes.IndexOf(this.targetElement);
121 }
122
123 public void Dispose()
124 {
125 this.parentElement.Add(this.siblingNodes);
126 }
127 }
128 }