aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-03-01 23:23:37 -0800
committerRob Mensching <rob@firegiant.com>2021-03-02 01:54:57 -0800
commit73bd35f56189da4e9f5aaf4625247078e0486887 (patch)
treeaf8d1256055a54e15148063a0dac14ad4d4c1e5a /src
parenta96d1a916bfcf35f77d48f70215d62b298bfb933 (diff)
downloadwix-73bd35f56189da4e9f5aaf4625247078e0486887.tar.gz
wix-73bd35f56189da4e9f5aaf4625247078e0486887.tar.bz2
wix-73bd35f56189da4e9f5aaf4625247078e0486887.zip
Optimize SourceLineNumber and add support for setting Parent
Diffstat (limited to 'src')
-rw-r--r--src/WixToolset.Data/SourceLineNumber.cs123
1 files changed, 80 insertions, 43 deletions
diff --git a/src/WixToolset.Data/SourceLineNumber.cs b/src/WixToolset.Data/SourceLineNumber.cs
index 8ec65201..970f17e7 100644
--- a/src/WixToolset.Data/SourceLineNumber.cs
+++ b/src/WixToolset.Data/SourceLineNumber.cs
@@ -35,10 +35,34 @@ namespace WixToolset.Data
35 } 35 }
36 36
37 /// <summary> 37 /// <summary>
38 /// Constructor for a source with a parent and no line information.
39 /// </summary>
40 /// <param name="fileName">File name of the source.</param>
41 /// <param name="parent">Parent of this source line number</param>
42 public SourceLineNumber(string fileName, SourceLineNumber parent)
43 {
44 this.FileName = fileName;
45 this.Parent = parent;
46 }
47
48 /// <summary>
49 /// Constructor for a source with a parent and line information.
50 /// </summary>
51 /// <param name="fileName">File name of the source.</param>
52 /// <param name="parent">Parent of this source line number</param>
53 /// <param name="lineNumber">Line number of the source.</param>
54 public SourceLineNumber(string fileName, SourceLineNumber parent, int lineNumber)
55 {
56 this.FileName = fileName;
57 this.Parent = parent;
58 this.LineNumber = lineNumber;
59 }
60
61 /// <summary>
38 /// Gets the file name of the source. 62 /// Gets the file name of the source.
39 /// </summary> 63 /// </summary>
40 /// <value>File name for the source.</value> 64 /// <value>File name for the source.</value>
41 public string FileName { get; private set; } 65 public string FileName { get; }
42 66
43 /// <summary> 67 /// <summary>
44 /// Gets or sets the line number of the source. 68 /// Gets or sets the line number of the source.
@@ -49,19 +73,13 @@ namespace WixToolset.Data
49 /// <summary> 73 /// <summary>
50 /// Gets or sets the parent source line number that included this source line number. 74 /// Gets or sets the parent source line number that included this source line number.
51 /// </summary> 75 /// </summary>
52 public SourceLineNumber Parent { get; set; } 76 public SourceLineNumber Parent { get; private set; }
53 77
54 /// <summary> 78 /// <summary>
55 /// Gets the file name and line information. 79 /// Gets the file name and line information.
56 /// </summary> 80 /// </summary>
57 /// <value>File name and line information.</value> 81 /// <value>File name and line information.</value>
58 public string QualifiedFileName 82 public string QualifiedFileName => this.LineNumber.HasValue ? String.Concat(this.FileName, "*", this.LineNumber) : this.FileName;
59 {
60 get
61 {
62 return this.LineNumber.HasValue ? String.Concat(this.FileName, "*", this.LineNumber) : this.FileName;
63 }
64 }
65 83
66 internal static SourceLineNumber Deserialize(JsonObject jsonObject) 84 internal static SourceLineNumber Deserialize(JsonObject jsonObject)
67 { 85 {
@@ -101,37 +119,46 @@ namespace WixToolset.Data
101 /// <param name="encodedSourceLineNumbers">Encoded string to parse.</param> 119 /// <param name="encodedSourceLineNumbers">Encoded string to parse.</param>
102 public static SourceLineNumber CreateFromEncoded(string encodedSourceLineNumbers) 120 public static SourceLineNumber CreateFromEncoded(string encodedSourceLineNumbers)
103 { 121 {
104 string[] linesSplit = encodedSourceLineNumbers.Split('|'); 122 var linesSplitIndex = encodedSourceLineNumbers.IndexOf('|');
105 123
106 SourceLineNumber first = null; 124 // The most common case is that there is a single encoded line,
107 SourceLineNumber parent = null; 125 // so optimize for that case.
108 for (int i = 0; i < linesSplit.Length; ++i) 126 if (linesSplitIndex < 0)
109 { 127 {
110 string[] filenameSplit = linesSplit[i].Split('*'); 128 return DecodeSourceLineNumber(encodedSourceLineNumbers, 0, -1);
111 SourceLineNumber source; 129 }
112 130 else // decode the multiple lines.
113 if (2 == filenameSplit.Length) 131 {
114 { 132 var startLine = 0;
115 source = new SourceLineNumber(filenameSplit[0], Convert.ToInt32(filenameSplit[1]));
116 }
117 else
118 {
119 source = new SourceLineNumber(filenameSplit[0]);
120 }
121 133
122 if (null != parent) 134 SourceLineNumber first = null;
135 SourceLineNumber parent = null;
136 while (startLine < encodedSourceLineNumbers.Length)
123 { 137 {
124 parent.Parent = source; 138 var source = DecodeSourceLineNumber(encodedSourceLineNumbers, startLine, linesSplitIndex - 1);
139
140 if (null != parent)
141 {
142 parent.Parent = source;
143 }
144
145 parent = source;
146 if (null == first)
147 {
148 first = parent;
149 }
150
151 if (linesSplitIndex < 0)
152 {
153 break;
154 }
155
156 startLine = linesSplitIndex + 1;
157 linesSplitIndex = encodedSourceLineNumbers.IndexOf('|', startLine);
125 } 158 }
126 159
127 parent = source; 160 return first;
128 if (null == first)
129 {
130 first = parent;
131 }
132 } 161 }
133
134 return first;
135 } 162 }
136 163
137 /// <summary> 164 /// <summary>
@@ -159,11 +186,8 @@ namespace WixToolset.Data
159 /// <param name="offset">Optional line number offset into XML file not already included in the line information.</param> 186 /// <param name="offset">Optional line number offset into XML file not already included in the line information.</param>
160 public static SourceLineNumber CreateFromXObject(XObject node, int offset = 0) 187 public static SourceLineNumber CreateFromXObject(XObject node, int offset = 0)
161 { 188 {
162 string uri = node.BaseUri; 189 var result = CreateFromUri(node.BaseUri);
163 IXmlLineInfo lineInfo = node as IXmlLineInfo; 190 if (null != result && node is IXmlLineInfo lineInfo)
164
165 SourceLineNumber result = CreateFromUri(uri);
166 if (null != result && null != lineInfo)
167 { 191 {
168 result.LineNumber = lineInfo.LineNumber + offset; 192 result.LineNumber = lineInfo.LineNumber + offset;
169 } 193 }
@@ -191,12 +215,12 @@ namespace WixToolset.Data
191 /// </summary> 215 /// </summary>
192 public string GetEncoded() 216 public string GetEncoded()
193 { 217 {
194 StringBuilder sb = new StringBuilder(this.QualifiedFileName); 218 var sb = new StringBuilder(this.QualifiedFileName);
195 219
196 for (SourceLineNumber source = this.Parent; null != source; source = source.Parent) 220 for (var parent = this.Parent; null != parent; parent = parent.Parent)
197 { 221 {
198 sb.Append("|"); 222 sb.Append("|");
199 sb.Append(source.QualifiedFileName); 223 sb.Append(parent.QualifiedFileName);
200 } 224 }
201 225
202 return sb.ToString(); 226 return sb.ToString();
@@ -209,8 +233,7 @@ namespace WixToolset.Data
209 /// <returns>True if SourceLineNumbers are equivalent.</returns> 233 /// <returns>True if SourceLineNumbers are equivalent.</returns>
210 public override bool Equals(object obj) 234 public override bool Equals(object obj)
211 { 235 {
212 SourceLineNumber other = obj as SourceLineNumber; 236 return obj is SourceLineNumber other &&
213 return null != other &&
214 this.LineNumber.HasValue == other.LineNumber.HasValue && 237 this.LineNumber.HasValue == other.LineNumber.HasValue &&
215 (!this.LineNumber.HasValue || this.LineNumber == other.LineNumber) && 238 (!this.LineNumber.HasValue || this.LineNumber == other.LineNumber) &&
216 this.FileName.Equals(other.FileName, StringComparison.OrdinalIgnoreCase) && 239 this.FileName.Equals(other.FileName, StringComparison.OrdinalIgnoreCase) &&
@@ -234,5 +257,19 @@ namespace WixToolset.Data
234 { 257 {
235 return this.LineNumber.HasValue && !String.IsNullOrEmpty(this.FileName) ? String.Concat(this.FileName, "(", this.LineNumber, ")") : this.FileName ?? String.Empty; 258 return this.LineNumber.HasValue && !String.IsNullOrEmpty(this.FileName) ? String.Concat(this.FileName, "(", this.LineNumber, ")") : this.FileName ?? String.Empty;
236 } 259 }
260
261 private static SourceLineNumber DecodeSourceLineNumber(string encoded, int startIndex, int endIndex)
262 {
263 if (endIndex < 0)
264 {
265 endIndex = encoded.Length - 1;
266 }
267
268 var count = endIndex - startIndex;
269 var filenameSplitIndex = encoded.LastIndexOf('*', endIndex - 1, count);
270 return (filenameSplitIndex < 0) ? new SourceLineNumber(encoded) :
271 new SourceLineNumber(encoded.Substring(startIndex, filenameSplitIndex - startIndex),
272 Convert.ToInt32(encoded.Substring(filenameSplitIndex + 1, endIndex - filenameSplitIndex)));
273 }
237 } 274 }
238} 275}