src/SSC/ParallelNode.cs

実行済み 156 · 未実行 8 · 対象外 235
Coverage source: 043e27b9e5febd713c747d2558802e450fad8edd

実行済みCoberturaのhit数が1以上の行です。
未実行カバレッジ対象ですがhit数が0の行です。
対象外Coberturaに実行対象として記録されていない行です。
行状態HitsSource
1 対象外 namespace SSC;
2 対象外
3 対象外 public sealed class ParallelNode<T> : Parallel<T>, IParallelNode, IParallelNodeInternal
4 対象外 {
5 対象外 private readonly T?[] _values;
6 対象外 private readonly NodePresenceState[] _states;
7 対象外 private readonly bool _isScalarNode;
8 対象外 private readonly bool _hasRuntimeTypeMismatch;
9 実行済み 908 private readonly Dictionary<string, IReadOnlyList<IParallelNode>> _children = new(StringComparer.Ordinal);
10 実行済み 908 private readonly Dictionary<string, NodePresenceState[]> _containerPresenceStates = new(StringComparer.Ordinal);
11 実行済み 908 private readonly Dictionary<string, IParallelNode> _memberNodes = new(StringComparer.Ordinal);
12 実行済み 908 private readonly List<string> _directChildOrder = [];
13 対象外
14 対象外 /// <summary>
15 対象外 /// 位置合わせ済みのモデル値と存在状態から比較ノードを初期化し、必要に応じてnull以外の実行時型の違いを不一致として扱います。
16 対象外 /// </summary>
17 対象外 /// <param name="values">モデルインデックスで位置合わせした値。</param>
18 対象外 /// <param name="states"><paramref name="values"/>と位置合わせした存在状態。</param>
19 対象外 /// <param name="keyText">存在する場合にこのノードを識別するキーの表示テキスト。</param>
20 対象外 /// <param name="keyValue">存在する場合にキー付きコレクション要素の位置合わせに使用する生のキー値。</param>
21 対象外 /// <param name="keyComparer">キーによる位置合わせで必要な場合に<paramref name="keyValue"/>に使用する比較子。</param>
22 対象外 /// <param name="isScalarNode">このノードが子メンバーではなく値を直接比較する場合は<see langword="true"/>。</param>
23 対象外 /// <param name="detectRuntimeTypeMismatch">実行時型が異なる位置合わせ済みの存在値を不一致として記録する場合は<see langword="true"/>。</param>
24 実行済み 908 internal ParallelNode(
25 実行済み 908 T?[] values,
26 実行済み 908 NodePresenceState[] states,
27 実行済み 908 string? keyText,
28 実行済み 908 object? keyValue = null,
29 実行済み 908 IEqualityComparer<object>? keyComparer = null,
30 実行済み 908 bool isScalarNode = false,
31 実行済み 908 bool detectRuntimeTypeMismatch = false)
32 対象外 {
33 実行済み 908 _values = values;
34 実行済み 908 _states = states;
35 実行済み 908 _isScalarNode = isScalarNode;
36 実行済み 908 _hasRuntimeTypeMismatch = detectRuntimeTypeMismatch && DetectRuntimeTypeMismatch(values, states);
37 実行済み 908 KeyText = keyText;
38 実行済み 908 KeyValue = keyValue;
39 実行済み 908 KeyComparer = keyComparer;
40 実行済み 908 }
41 対象外
42 実行済み 284 public string? KeyText { get; }
43 対象外
44 実行済み 52 internal object? KeyValue { get; }
45 対象外
46 実行済み 64 internal IEqualityComparer<object>? KeyComparer { get; }
47 対象外
48 対象外 /// <summary>
49 対象外 /// 位置合わせ済みの存在値に異なる実行時型があり、メンバーへ下降せずノードレベルの不一致として報告する必要があるかを取得します。
50 対象外 /// </summary>
51 実行済み 899 internal bool HasRuntimeTypeMismatch => _hasRuntimeTypeMismatch;
52 対象外
53 実行済み 816 public int Count => _values.Length;
54 対象外
55 実行済み 3 public bool AllPresent => _states.All(state => state == NodePresenceState.PresentValue);
56 対象外
57 実行済み 6 public bool AnyPresent => _states.Any(state => state != NodePresenceState.Missing);
58 対象外
59 対象外 public T? this[int modelIndex]
60 対象外 {
61 対象外 get
62 対象外 {
63 実行済み 138 ValidateIndex(modelIndex);
64 実行済み 137 return _values[modelIndex];
65 対象外 }
66 対象外 }
67 対象外
68 対象外 public static ParallelNode<T> CreateLeaf(IReadOnlyList<T?> values, IReadOnlyList<ValueState> states, string? keyText = null)
69 対象外 {
70 実行済み 10 ArgumentNullException.ThrowIfNull(values);
71 実行済み 10 ArgumentNullException.ThrowIfNull(states);
72 実行済み 10 if (values.Count != states.Count)
73 対象外 {
74 実行済み 1 throw new ArgumentException(
75 実行済み 1 $"values count '{values.Count}' must match states count '{states.Count}'.",
76 実行済み 1 nameof(states));
77 対象外 }
78 対象外
79 実行済み 9 var presenceStates = new NodePresenceState[states.Count];
80 実行済み 56 for (var index = 0; index < states.Count; index++)
81 対象外 {
82 実行済み 19 presenceStates[index] = states[index] == ValueState.Missing
83 実行済み 19 ? NodePresenceState.Missing
84 実行済み 19 : values[index] is null
85 実行済み 19 ? NodePresenceState.PresentNull
86 実行済み 19 : NodePresenceState.PresentValue;
87 対象外 }
88 対象外
89 実行済み 9 return new ParallelNode<T>(values.ToArray(), presenceStates, keyText, isScalarNode: true);
90 対象外 }
91 対象外
92 対象外 public ValueState GetState(int modelIndex)
93 対象外 {
94 実行済み 786 ValidateIndex(modelIndex);
95 実行済み 785 var baseState = _states[modelIndex];
96 実行済み 785 if (baseState == NodePresenceState.Missing)
97 対象外 {
98 実行済み 40 return ValueState.Missing;
99 対象外 }
100 対象外
101 実行済み 745 if (_states.Length <= 1)
102 対象外 {
103 未実行 0 return ValueState.Missing;
104 対象外 }
105 対象外
106 実行済み 745 if (_hasRuntimeTypeMismatch)
107 対象外 {
108 実行済み 4 return ValueState.Mismatched;
109 対象外 }
110 対象外
111 実行済み 741 if (!_isScalarNode)
112 対象外 {
113 実行済み 49 if (HasPresenceMismatch(_states))
114 対象外 {
115 実行済み 8 return ValueState.Mismatched;
116 対象外 }
117 対象外
118 実行済み 150 foreach (var containerPresenceStates in _containerPresenceStates.Values)
119 対象外 {
120 実行済み 34 if (HasPresenceMismatch(containerPresenceStates))
121 対象外 {
122 未実行 0 return ValueState.Mismatched;
123 対象外 }
124 対象外 }
125 対象外
126 実行済み 100 if (_memberNodes.Values.Any(node => node.HasDifferences()))
127 対象外 {
128 実行済み 26 return ValueState.Mismatched;
129 対象外 }
130 対象外
131 実行済み 43 if (_children.Values.SelectMany(nodes => nodes).Any(node => node.HasDifferences()))
132 対象外 {
133 実行済み 12 return ValueState.Mismatched;
134 対象外 }
135 対象外
136 実行済み 3 return ValueState.Matched;
137 対象外 }
138 対象外
139 実行済み 692 var matched = true;
140 実行済み 3364 for (var index = 0; index < _states.Length; index++)
141 対象外 {
142 実行済み 1325 if (index == modelIndex)
143 対象外 {
144 対象外 continue;
145 対象外 }
146 対象外
147 実行済み 692 if (_states[index] == NodePresenceState.Missing)
148 対象外 {
149 実行済み 6 matched = false;
150 実行済み 6 break;
151 対象外 }
152 対象外
153 実行済み 686 if (_states[index] != baseState)
154 対象外 {
155 実行済み 2 matched = false;
156 実行済み 2 break;
157 対象外 }
158 対象外
159 実行済み 684 if (baseState == NodePresenceState.PresentValue
160 実行済み 684 && !EqualityComparer<T?>.Default.Equals(_values[modelIndex], _values[index]))
161 対象外 {
162 実行済み 327 matched = false;
163 実行済み 327 break;
164 対象外 }
165 対象外 }
166 対象外
167 実行済み 692 return ValueStateExtensions.ToComparisonState(hasComparisonTarget: true, matched);
168 未実行 0 }
169 対象外
170 対象外 public object? GetValue(int modelIndex)
171 対象外 {
172 実行済み 224 ValidateIndex(modelIndex);
173 実行済み 223 return _states[modelIndex] == NodePresenceState.PresentValue ? _values[modelIndex] : null;
174 対象外 }
175 対象外
176 対象外 public override string ToString()
177 対象外 {
178 実行済み 9 return ParallelDisplayFormatter.FormatSlots(
179 実行済み 9 Count,
180 実行済み 27 modelIndex => new ParallelDisplaySlot(GetValue(modelIndex), GetState(modelIndex)));
181 対象外 }
182 対象外
183 対象外 public bool HasDifferences()
184 対象外 {
185 実行済み 514 if (_states.Length <= 1)
186 対象外 {
187 未実行 0 return false;
188 対象外 }
189 対象外
190 実行済み 514 if (_hasRuntimeTypeMismatch)
191 対象外 {
192 実行済み 2 return true;
193 対象外 }
194 対象外
195 実行済み 512 if (_isScalarNode)
196 対象外 {
197 実行済み 1448 for (var modelIndex = 0; modelIndex < _states.Length; modelIndex++)
198 対象外 {
199 実行済み 552 if (GetState(modelIndex) == ValueState.Mismatched)
200 対象外 {
201 実行済み 208 return true;
202 対象外 }
203 対象外 }
204 対象外
205 実行済み 172 return false;
206 対象外 }
207 対象外
208 実行済み 132 if (HasPresenceMismatch(_states))
209 対象外 {
210 実行済み 7 return true;
211 対象外 }
212 対象外
213 実行済み 441 foreach (var containerPresenceStates in _containerPresenceStates.Values)
214 対象外 {
215 実行済み 97 if (HasPresenceMismatch(containerPresenceStates))
216 対象外 {
217 実行済み 3 return true;
218 対象外 }
219 対象外 }
220 対象外
221 実行済み 509 foreach (var memberNode in _memberNodes.Values)
222 対象外 {
223 実行済み 170 if (memberNode.HasDifferences())
224 対象外 {
225 実行済み 75 return true;
226 対象外 }
227 対象外 }
228 対象外
229 実行済み 178 foreach (var childNodes in _children.Values)
230 対象外 {
231 実行済み 166 foreach (var childNode in childNodes)
232 対象外 {
233 実行済み 41 if (childNode.HasDifferences())
234 対象外 {
235 実行済み 38 return true;
236 対象外 }
237 対象外 }
238 対象外 }
239 対象外
240 実行済み 9 return false;
241 実行済み 116 }
242 対象外
243 対象外 public IReadOnlyList<ParallelChildSet> GetDirectChildren()
244 対象外 {
245 実行済み 180 if (_hasRuntimeTypeMismatch || _directChildOrder.Count == 0)
246 対象外 {
247 実行済み 57 return Array.Empty<ParallelChildSet>();
248 対象外 }
249 対象外
250 実行済み 123 var childSets = new ParallelChildSet[_directChildOrder.Count];
251 実行済み 632 for (var index = 0; index < _directChildOrder.Count; index++)
252 対象外 {
253 実行済み 193 var memberName = _directChildOrder[index];
254 実行済み 193 if (_memberNodes.TryGetValue(memberName, out var memberNode))
255 対象外 {
256 実行済み 114 childSets[index] = new ParallelChildSet(memberName, [memberNode], memberNode.HasDifferences());
257 実行済み 114 continue;
258 対象外 }
259 対象外
260 実行済み 79 var childNodes = _children[memberName];
261 実行済み 79 var hasDifferences = HasPresenceMismatch(_containerPresenceStates[memberName])
262 実行済み 132 || childNodes.Any(node => node.HasDifferences());
263 実行済み 79 childSets[index] = new ParallelChildSet(memberName, childNodes, hasDifferences);
264 対象外 }
265 対象外
266 実行済み 123 return childSets;
267 対象外 }
268 対象外
269 対象外 internal NodePresenceState GetPresenceState(int modelIndex)
270 対象外 {
271 実行済み 408 ValidateIndex(modelIndex);
272 実行済み 408 return _states[modelIndex];
273 対象外 }
274 対象外
275 対象外 public IReadOnlyList<ParallelNode<TElement>> GetChildren<TElement>(string memberName)
276 対象外 {
277 実行済み 113 if (!_children.TryGetValue(memberName, out var nodes))
278 対象外 {
279 未実行 0 return Array.Empty<ParallelNode<TElement>>();
280 対象外 }
281 対象外
282 実行済み 336 return nodes.Select(node => (ParallelNode<TElement>)node).ToArray();
283 対象外 }
284 対象外
285 実行済み 62 Type IParallelNodeInternal.ModelType => typeof(T);
286 対象外
287 対象外 bool IParallelNodeInternal.TryGetChildren(string memberName, out IReadOnlyList<IParallelNode> nodes)
288 対象外 {
289 実行済み 154 return _children.TryGetValue(memberName, out nodes!);
290 対象外 }
291 対象外
292 対象外 bool IParallelNodeInternal.TryGetMemberNode(string memberName, out IParallelNode node)
293 対象外 {
294 実行済み 345 return _memberNodes.TryGetValue(memberName, out node!);
295 対象外 }
296 対象外
297 対象外 bool IParallelNodeInternal.TryGetContainerPresenceStates(string memberName, out IReadOnlyList<NodePresenceState> states)
298 対象外 {
299 実行済み 5 if (_containerPresenceStates.TryGetValue(memberName, out var containerStates))
300 対象外 {
301 実行済み 5 states = containerStates;
302 実行済み 5 return true;
303 対象外 }
304 対象外
305 未実行 0 states = Array.Empty<NodePresenceState>();
306 未実行 0 return false;
307 対象外 }
308 対象外
309 対象外 NodePresenceState IParallelNodeInternal.GetPresenceState(int modelIndex)
310 対象外 {
311 実行済み 307 return GetPresenceState(modelIndex);
312 対象外 }
313 対象外
314 対象外 internal void SetChildren(string memberName, IReadOnlyList<IParallelNode> nodes, IReadOnlyList<NodePresenceState> presenceStates)
315 対象外 {
316 実行済み 183 RegisterDirectChild(memberName);
317 実行済み 183 _children[memberName] = nodes;
318 実行済み 183 _containerPresenceStates[memberName] = [.. presenceStates];
319 実行済み 183 }
320 対象外
321 対象外 internal void SetMemberNode(string memberName, IParallelNode node)
322 対象外 {
323 実行済み 568 RegisterDirectChild(memberName);
324 実行済み 568 _memberNodes[memberName] = node;
325 実行済み 568 }
326 対象外
327 対象外 private void RegisterDirectChild(string memberName)
328 対象外 {
329 実行済み 751 if (!_directChildOrder.Contains(memberName, StringComparer.Ordinal))
330 対象外 {
331 実行済み 751 _directChildOrder.Add(memberName);
332 対象外 }
333 実行済み 751 }
334 対象外
335 対象外 /// <summary>
336 対象外 /// 位置合わせ済みの存在値に複数のnull以外の実行時型が含まれるかを判定します。
337 対象外 /// </summary>
338 対象外 /// <param name="values">モデルインデックスで位置合わせした値。</param>
339 対象外 /// <param name="states"><paramref name="values"/>と位置合わせした存在状態。</param>
340 対象外 /// <returns>存在するnull以外の値のうち少なくとも2つの実行時型が異なる場合は<see langword="true"/>。それ以外の場合は<see langword="false"/>。</returns>
341 対象外 private static bool DetectRuntimeTypeMismatch(
342 対象外 IReadOnlyList<T?> values,
343 対象外 IReadOnlyList<NodePresenceState> states)
344 対象外 {
345 実行済み 190 Type? runtimeType = null;
346 実行済み 1136 for (var index = 0; index < states.Count; index++)
347 対象外 {
348 実行済み 379 if (states[index] != NodePresenceState.PresentValue || values[index] is null)
349 対象外 {
350 対象外 continue;
351 対象外 }
352 対象外
353 実行済み 300 var currentType = values[index]!.GetType();
354 実行済み 300 if (runtimeType is null)
355 対象外 {
356 実行済み 190 runtimeType = currentType;
357 実行済み 190 continue;
358 対象外 }
359 対象外
360 実行済み 110 if (runtimeType != currentType)
361 対象外 {
362 実行済み 1 return true;
363 対象外 }
364 対象外 }
365 対象外
366 実行済み 189 return false;
367 対象外 }
368 対象外
369 対象外 private static bool HasPresenceMismatch(IReadOnlyList<NodePresenceState> states)
370 対象外 {
371 実行済み 391 if (states.Count <= 1)
372 対象外 {
373 未実行 0 return false;
374 対象外 }
375 対象外
376 実行済み 391 var firstState = states[0];
377 実行済み 1514 for (var index = 1; index < states.Count; index++)
378 対象外 {
379 実行済み 391 if (states[index] != firstState)
380 対象外 {
381 実行済み 25 return true;
382 対象外 }
383 対象外 }
384 対象外
385 実行済み 366 return false;
386 対象外 }
387 対象外
388 対象外 private void ValidateIndex(int modelIndex)
389 対象外 {
390 実行済み 1556 if (modelIndex >= 0 && modelIndex < _values.Length)
391 対象外 {
392 実行済み 1553 return;
393 対象外 }
394 対象外
395 実行済み 3 throw new CompareExecutionException(
396 実行済み 3 CompareIssueCode.ModelIndexOutOfRange,
397 実行済み 3 $"modelIndex '{modelIndex}' is out of range for count '{_values.Length}'.");
398 対象外 }
399 対象外 }