src/SSC/ParallelPathAccessExtensions.cs

実行済み 222 · 未実行 8 · 対象外 237
Coverage source: 043e27b9e5febd713c747d2558802e450fad8edd

実行済みCoberturaのhit数が1以上の行です。
未実行カバレッジ対象ですがhit数が0の行です。
対象外Coberturaに実行対象として記録されていない行です。
行状態HitsSource
1 対象外 using SSC.Internal;
2 対象外
3 対象外 namespace SSC;
4 対象外
5 対象外 public static class ParallelPathAccessExtensions
6 対象外 {
7 対象外 public static IParallelNode? GetNodeByPath<T>(this CompareResult<T> result, string path)
8 対象外 {
9 実行済み 39 ArgumentNullException.ThrowIfNull(result);
10 実行済み 39 ArgumentNullException.ThrowIfNull(path);
11 対象外
12 実行済み 39 if (result.Root is not IParallelNode current)
13 対象外 {
14 未実行 0 return null;
15 対象外 }
16 対象外
17 実行済み 39 if (!XPathLikePathParser.TryParse(path, typeof(T).Name, out var parsedPath) || parsedPath is null)
18 対象外 {
19 実行済み 2 return null;
20 対象外 }
21 対象外
22 実行済み 218 foreach (var segment in parsedPath.Segments)
23 対象外 {
24 実行済み 76 if (!TryResolveSegment(current, segment, out var next))
25 対象外 {
26 実行済み 8 return null;
27 対象外 }
28 対象外
29 実行済み 68 current = next;
30 対象外 }
31 対象外
32 実行済み 29 return current;
33 実行済み 8 }
34 対象外
35 対象外 public static object? GetValueByPath<T>(this CompareResult<T> result, string path, int modelIndex)
36 対象外 {
37 実行済み 7 var node = result.GetNodeByPath(path);
38 実行済み 7 return node?.GetValue(modelIndex);
39 対象外 }
40 対象外
41 対象外 public static ValueState GetStateByPath<T>(this CompareResult<T> result, string path, int modelIndex)
42 対象外 {
43 実行済み 5 var node = result.GetNodeByPath(path);
44 実行済み 5 return node?.GetState(modelIndex) ?? ValueState.Missing;
45 対象外 }
46 対象外
47 対象外 public static IReadOnlyList<ParallelDiffEntry> GetDiffEntries<T>(this CompareResult<T> result)
48 対象外 {
49 実行済み 22 ArgumentNullException.ThrowIfNull(result);
50 対象外
51 実行済み 22 if (result.Root is not IParallelNode root)
52 対象外 {
53 未実行 0 return Array.Empty<ParallelDiffEntry>();
54 対象外 }
55 対象外
56 実行済み 22 var collector = new DiffEntryCollector(projector: null);
57 実行済み 22 collector.Collect(root);
58 実行済み 22 return collector.Entries;
59 対象外 }
60 対象外
61 対象外 /// <summary>
62 対象外 /// 標準差分 entry と、指定した投影器で生成した利用側定義 path の組を返します。
63 対象外 /// </summary>
64 対象外 /// <typeparam name="T">比較対象 model の型。</typeparam>
65 対象外 /// <param name="result">比較結果。</param>
66 対象外 /// <param name="projector">標準 path segment の扱いを決定する投影器。</param>
67 対象外 /// <returns>標準差分 entry と利用側定義 path の一覧。</returns>
68 対象外 /// <exception cref="ArgumentNullException">
69 対象外 /// <paramref name="result"/> または <paramref name="projector"/> が <see langword="null"/> の場合。
70 対象外 /// </exception>
71 対象外 /// <exception cref="InvalidOperationException">
72 対象外 /// 1件の差分 entry に含まれるすべての segment が省略され、利用側定義 path が空になる場合。
73 対象外 /// </exception>
74 対象外 public static IReadOnlyList<ParallelDiffEntryPathProjection> GetDiffEntryPathProjections<T>(
75 対象外 this CompareResult<T> result,
76 対象外 IParallelDiffPathProjector projector)
77 対象外 {
78 実行済み 35 ArgumentNullException.ThrowIfNull(result);
79 実行済み 34 ArgumentNullException.ThrowIfNull(projector);
80 対象外
81 実行済み 33 if (result.Root is not IParallelNode root)
82 対象外 {
83 実行済み 1 return Array.Empty<ParallelDiffEntryPathProjection>();
84 対象外 }
85 対象外
86 実行済み 32 var collector = new DiffEntryCollector(projector);
87 実行済み 32 collector.Collect(root);
88 実行済み 30 return collector.Projections;
89 対象外 }
90 対象外
91 対象外 private static bool TryResolveSegment(IParallelNode current, XPathLikePathSegment segment, out IParallelNode next)
92 対象外 {
93 実行済み 76 if (current is not IParallelNodeInternal internalNode)
94 対象外 {
95 未実行 0 next = null!;
96 未実行 0 return false;
97 対象外 }
98 対象外
99 実行済み 76 if (segment.Selector is null)
100 対象外 {
101 実行済み 27 return internalNode.TryGetMemberNode(segment.MemberName, out next!);
102 対象外 }
103 対象外
104 実行済み 49 if (!internalNode.TryGetChildren(segment.MemberName, out var childNodes))
105 対象外 {
106 実行済み 1 next = null!;
107 実行済み 1 return false;
108 対象外 }
109 対象外
110 実行済み 48 return TrySelectChild(childNodes, segment.Selector, out next);
111 対象外 }
112 対象外
113 対象外 private static bool TrySelectChild(
114 対象外 IReadOnlyList<IParallelNode> childNodes,
115 対象外 XPathLikePathSelector selector,
116 対象外 out IParallelNode next)
117 対象外 {
118 実行済み 48 if (selector.Kind == XPathLikePathSelectorKind.Ordinal)
119 対象外 {
120 実行済み 5 var ordinal = selector.Ordinal!.Value;
121 実行済み 5 if (ordinal < 0 || ordinal >= childNodes.Count)
122 対象外 {
123 未実行 0 next = null!;
124 未実行 0 return false;
125 対象外 }
126 対象外
127 実行済み 5 next = childNodes[ordinal];
128 実行済み 5 return next.KeyText is null;
129 対象外 }
130 対象外
131 実行済み 43 next = childNodes.FirstOrDefault(child =>
132 実行済み 93 string.Equals(child.KeyText, selector.KeyText, StringComparison.Ordinal))!;
133 実行済み 43 return next is not null;
134 対象外 }
135 対象外
136 対象外 private sealed class DiffEntryCollector
137 対象外 {
138 対象外 private readonly IParallelDiffPathProjector? _projector;
139 実行済み 54 private readonly List<DiffPathFrame> _frames = [];
140 実行済み 54 private readonly List<ParallelDiffEntry> _entries = [];
141 実行済み 54 private readonly List<ParallelDiffEntryPathProjection> _projections = [];
142 対象外
143 実行済み 54 public DiffEntryCollector(IParallelDiffPathProjector? projector)
144 対象外 {
145 実行済み 54 _projector = projector;
146 実行済み 54 }
147 対象外
148 実行済み 22 public IReadOnlyList<ParallelDiffEntry> Entries => _entries;
149 対象外
150 実行済み 30 public IReadOnlyList<ParallelDiffEntryPathProjection> Projections => _projections;
151 対象外
152 対象外 public void Collect(IParallelNode root)
153 対象外 {
154 実行済み 214 foreach (var childSet in root.GetDirectChildren())
155 対象外 {
156 実行済み 54 AddChildSetDiffEntries(childSet, root);
157 対象外 }
158 実行済み 52 }
159 対象外
160 対象外 private void AddNodeDiffEntries(IParallelNode node)
161 対象外 {
162 実行済み 129 if (HasOwnPresenceMismatch(node))
163 対象外 {
164 実行済み 7 AddEntry(CreateNodeEntry(node));
165 実行済み 7 return;
166 対象外 }
167 対象外
168 実行済み 122 var childSets = node.GetDirectChildren();
169 実行済み 122 if (childSets.Count == 0)
170 対象外 {
171 実行済み 57 if (node.HasDifferences())
172 対象外 {
173 実行済み 57 AddEntry(CreateNodeEntry(node));
174 対象外 }
175 対象外
176 実行済み 55 return;
177 対象外 }
178 対象外
179 実行済み 390 foreach (var childSet in childSets)
180 対象外 {
181 実行済み 131 AddChildSetDiffEntries(childSet, node);
182 対象外 }
183 実行済み 63 }
184 対象外
185 対象外 private void AddChildSetDiffEntries(
186 対象外 ParallelChildSet childSet,
187 対象外 IParallelNode parentNode)
188 対象外 {
189 実行済み 185 if (!childSet.HasDifferences)
190 対象外 {
191 実行済み 64 return;
192 対象外 }
193 対象外
194 実行済み 121 if (parentNode is IParallelNodeInternal internalParent
195 実行済み 121 && internalParent.TryGetMemberNode(childSet.Name, out var memberNode))
196 対象外 {
197 実行済み 62 PushFrame(
198 実行済み 62 ParallelDiffPathSegment.Member(childSet.Name),
199 実行済み 62 parentNode,
200 実行済み 62 memberNode,
201 実行済み 62 childSet.Nodes);
202 対象外 try
203 対象外 {
204 実行済み 62 AddNodeDiffEntries(memberNode);
205 実行済み 60 }
206 対象外 finally
207 対象外 {
208 実行済み 62 PopFrame();
209 実行済み 62 }
210 対象外
211 実行済み 60 return;
212 対象外 }
213 対象外
214 実行済み 59 if (childSet.Nodes.Count == 0)
215 対象外 {
216 実行済み 6 if (parentNode is IParallelNodeInternal containerParent
217 実行済み 6 && containerParent.TryGetContainerPresenceStates(childSet.Name, out var states))
218 対象外 {
219 実行済み 6 PushFrame(
220 実行済み 6 ParallelDiffPathSegment.Member(childSet.Name),
221 実行済み 6 parentNode,
222 実行済み 6 node: null,
223 実行済み 6 Array.Empty<IParallelNode>());
224 対象外 try
225 対象外 {
226 実行済み 6 AddEntry(CreateContainerPresenceEntry(parentNode, states));
227 実行済み 6 }
228 対象外 finally
229 対象外 {
230 実行済み 6 PopFrame();
231 実行済み 6 }
232 対象外 }
233 対象外
234 実行済み 6 return;
235 対象外 }
236 対象外
237 実行済み 236 for (var ordinal = 0; ordinal < childSet.Nodes.Count; ordinal++)
238 対象外 {
239 実行済み 67 var childNode = childSet.Nodes[ordinal];
240 実行済み 67 var segment = childNode.KeyText is null
241 実行済み 67 ? ParallelDiffPathSegment.Ordinal(childSet.Name, ordinal)
242 実行済み 67 : ParallelDiffPathSegment.StandardKey(childSet.Name, childNode.KeyText);
243 対象外
244 実行済み 67 PushFrame(segment, parentNode, childNode, childSet.Nodes);
245 対象外 try
246 対象外 {
247 実行済み 67 AddNodeDiffEntries(childNode);
248 実行済み 65 }
249 対象外 finally
250 対象外 {
251 実行済み 67 PopFrame();
252 実行済み 67 }
253 対象外 }
254 実行済み 51 }
255 対象外
256 対象外 private void PushFrame(
257 対象外 ParallelDiffPathSegment standardSegment,
258 対象外 IParallelNode parentNode,
259 対象外 IParallelNode? node,
260 対象外 IReadOnlyList<IParallelNode> siblings)
261 対象外 {
262 実行済み 135 _frames.Add(new DiffPathFrame(
263 実行済み 135 standardSegment,
264 実行済み 135 parentNode,
265 実行済み 135 node,
266 実行済み 135 siblings));
267 実行済み 135 }
268 対象外
269 対象外 private void PopFrame()
270 対象外 {
271 実行済み 135 _frames.RemoveAt(_frames.Count - 1);
272 実行済み 135 }
273 対象外
274 対象外 private void AddEntry(ParallelDiffEntry entry)
275 対象外 {
276 実行済み 70 if (_projector is null)
277 対象外 {
278 実行済み 30 _entries.Add(entry);
279 実行済み 30 return;
280 対象外 }
281 対象外
282 実行済み 40 _projections.Add(CreateProjection(entry, _projector));
283 実行済み 38 }
284 対象外
285 対象外 private ParallelDiffEntryPathProjection CreateProjection(
286 対象外 ParallelDiffEntry entry,
287 対象外 IParallelDiffPathProjector projector)
288 対象外 {
289 実行済み 40 var nodeContexts = _frames
290 実行済み 82 .Select(frame => new ParallelDiffPathNodeContext(
291 実行済み 82 frame.StandardSegment,
292 実行済み 82 frame.ParentNode,
293 実行済み 82 frame.Node,
294 実行済み 82 frame.Siblings))
295 実行済み 40 .ToArray();
296 実行済み 40 var projectedSegments = new List<ParallelDiffPathSegment>(_frames.Count);
297 実行済み 40 var projectedParentSegmentCount = 0;
298 対象外
299 実行済み 240 for (var index = 0; index < nodeContexts.Length; index++)
300 対象外 {
301 実行済み 81 IReadOnlyList<ParallelDiffPathNodeContext> ancestors = index == 0
302 実行済み 81 ? Array.Empty<ParallelDiffPathNodeContext>()
303 実行済み 81 : nodeContexts[..index];
304 実行済み 81 var context = new ParallelDiffPathProjectionContext(
305 実行済み 81 ancestors,
306 実行済み 81 nodeContexts[index]);
307 実行済み 81 var projection = projector.Project(context);
308 対象外
309 実行済み 80 switch (projection.Kind)
310 対象外 {
311 対象外 case ParallelDiffPathSegmentProjectionKind.KeepStandard:
312 実行済み 46 projectedSegments.Add(nodeContexts[index].StandardSegment);
313 実行済み 46 break;
314 対象外 case ParallelDiffPathSegmentProjectionKind.Replace:
315 実行済み 30 projectedSegments.Add(projection.Replacement
316 実行済み 30 ?? throw new InvalidOperationException(
317 実行済み 30 "Replace projection must contain a replacement segment."));
318 実行済み 30 break;
319 対象外 case ParallelDiffPathSegmentProjectionKind.Omit:
320 対象外 break;
321 対象外 default:
322 未実行 0 throw new InvalidOperationException(
323 未実行 0 $"Unknown diff path segment projection kind '{projection.Kind}'.");
324 対象外 }
325 対象外
326 実行済み 80 if (index == nodeContexts.Length - 2)
327 対象外 {
328 実行済み 30 projectedParentSegmentCount = projectedSegments.Count;
329 対象外 }
330 対象外 }
331 対象外
332 実行済み 39 if (projectedSegments.Count == 0)
333 対象外 {
334 実行済み 1 throw new InvalidOperationException(
335 実行済み 1 $"Projected diff path for standard path '{entry.Path}' cannot be empty.");
336 対象外 }
337 対象外
338 実行済み 38 var projectedPath = ParallelDiffPathFormatter.Format(projectedSegments);
339 実行済み 38 var projectedParentPath = nodeContexts.Length <= 1
340 実行済み 38 || projectedParentSegmentCount == 0
341 実行済み 38 ? null
342 実行済み 38 : ParallelDiffPathFormatter.Format(
343 実行済み 38 projectedSegments,
344 実行済み 38 projectedParentSegmentCount);
345 対象外
346 実行済み 38 return new ParallelDiffEntryPathProjection(
347 実行済み 38 entry,
348 実行済み 38 projectedPath,
349 実行済み 38 projectedParentPath);
350 対象外 }
351 対象外
352 対象外 private ParallelDiffEntry CreateNodeEntry(IParallelNode node)
353 対象外 {
354 実行済み 64 var values = new ParallelDiffValue[node.Count];
355 実行済み 380 for (var modelIndex = 0; modelIndex < node.Count; modelIndex++)
356 対象外 {
357 実行済み 126 values[modelIndex] = new ParallelDiffValue
358 実行済み 126 {
359 実行済み 126 ModelIndex = modelIndex,
360 実行済み 126 Value = node.GetValue(modelIndex),
361 実行済み 126 State = node.GetState(modelIndex),
362 実行済み 126 };
363 対象外 }
364 対象外
365 実行済み 64 return new ParallelDiffEntry
366 実行済み 64 {
367 実行済み 64 Path = CreateStandardPath(),
368 実行済み 64 ParentPath = CreateStandardParentPath(),
369 実行済み 64 Kind = ParallelDiffEntryKind.Node,
370 実行済み 64 ParentNode = _frames[^1].ParentNode,
371 実行済み 64 Node = node,
372 実行済み 64 Values = values,
373 実行済み 64 };
374 対象外 }
375 対象外
376 対象外 private ParallelDiffEntry CreateContainerPresenceEntry(
377 対象外 IParallelNode parentNode,
378 対象外 IReadOnlyList<NodePresenceState> states)
379 対象外 {
380 実行済み 6 var values = new ParallelDiffValue[states.Count];
381 実行済み 36 for (var modelIndex = 0; modelIndex < states.Count; modelIndex++)
382 対象外 {
383 実行済み 12 values[modelIndex] = new ParallelDiffValue
384 実行済み 12 {
385 実行済み 12 ModelIndex = modelIndex,
386 実行済み 12 Value = null,
387 実行済み 12 State = states[modelIndex] == NodePresenceState.Missing
388 実行済み 12 ? ValueState.Missing
389 実行済み 12 : ValueState.Mismatched,
390 実行済み 12 };
391 対象外 }
392 対象外
393 実行済み 6 return new ParallelDiffEntry
394 実行済み 6 {
395 実行済み 6 Path = CreateStandardPath(),
396 実行済み 6 ParentPath = CreateStandardParentPath(),
397 実行済み 6 Kind = ParallelDiffEntryKind.ContainerPresence,
398 実行済み 6 ParentNode = parentNode,
399 実行済み 6 Node = null,
400 実行済み 6 Values = values,
401 実行済み 6 };
402 対象外 }
403 対象外
404 対象外 private string CreateStandardPath()
405 対象外 {
406 実行済み 70 var segments = _frames
407 実行済み 146 .Select(frame => frame.StandardSegment)
408 実行済み 70 .ToArray();
409 実行済み 70 return ParallelDiffPathFormatter.Format(segments);
410 対象外 }
411 対象外
412 対象外 private string? CreateStandardParentPath()
413 対象外 {
414 実行済み 70 if (_frames.Count <= 1)
415 対象外 {
416 実行済み 17 return null;
417 対象外 }
418 対象外
419 実行済み 53 var segments = _frames
420 実行済み 129 .Select(frame => frame.StandardSegment)
421 実行済み 53 .ToArray();
422 実行済み 53 return ParallelDiffPathFormatter.Format(segments, segments.Length - 1);
423 対象外 }
424 対象外
425 対象外 private static bool HasOwnPresenceMismatch(IParallelNode node)
426 対象外 {
427 実行済み 129 if (node.Count <= 1 || node is not IParallelNodeInternal internalNode)
428 対象外 {
429 実行済み 3 return false;
430 対象外 }
431 対象外
432 実行済み 126 var first = internalNode.GetPresenceState(0);
433 実行済み 490 for (var modelIndex = 1; modelIndex < node.Count; modelIndex++)
434 対象外 {
435 実行済み 126 if (internalNode.GetPresenceState(modelIndex) != first)
436 対象外 {
437 実行済み 7 return true;
438 対象外 }
439 対象外 }
440 対象外
441 実行済み 119 return false;
442 対象外 }
443 対象外 }
444 対象外
445 対象外 private sealed class DiffPathFrame
446 対象外 {
447 実行済み 135 public DiffPathFrame(
448 実行済み 135 ParallelDiffPathSegment standardSegment,
449 実行済み 135 IParallelNode parentNode,
450 実行済み 135 IParallelNode? node,
451 実行済み 135 IReadOnlyList<IParallelNode> siblings)
452 対象外 {
453 実行済み 135 StandardSegment = standardSegment;
454 実行済み 135 ParentNode = parentNode;
455 実行済み 135 Node = node;
456 実行済み 135 Siblings = siblings;
457 実行済み 135 }
458 対象外
459 実行済み 357 public ParallelDiffPathSegment StandardSegment { get; }
460 対象外
461 実行済み 146 public IParallelNode ParentNode { get; }
462 対象外
463 実行済み 82 public IParallelNode? Node { get; }
464 対象外
465 実行済み 82 public IReadOnlyList<IParallelNode> Siblings { get; }
466 対象外 }
467 対象外 }