src/SSC/ParallelDynamicAccessExtensions.cs

実行済み 146 · 未実行 51 · 対象外 238
Coverage source: 043e27b9e5febd713c747d2558802e450fad8edd

実行済みCoberturaのhit数が1以上の行です。
未実行カバレッジ対象ですがhit数が0の行です。
対象外Coberturaに実行対象として記録されていない行です。
行状態HitsSource
1 対象外 using System.Dynamic;
2 対象外 using System.Reflection;
3 対象外
4 対象外 namespace SSC;
5 対象外
6 対象外 public static class ParallelDynamicAccessExtensions
7 対象外 {
8 対象外 public static dynamic? AsDynamic<T>(this CompareResult<T> result)
9 対象外 {
10 実行済み 15 ArgumentNullException.ThrowIfNull(result);
11 実行済み 15 if (result.Root is null)
12 対象外 {
13 実行済み 1 return null;
14 対象外 }
15 対象外
16 実行済み 14 if (result.Root is not IParallelNode parallelNode || parallelNode is not IParallelNodeInternal)
17 対象外 {
18 実行済み 1 throw new ArgumentException(
19 実行済み 1 "AsDynamic can be used only with compare result nodes.",
20 実行済み 1 nameof(result));
21 対象外 }
22 対象外
23 実行済み 13 return DynamicParallelNodeView.From(parallelNode, result.Configuration);
24 対象外 }
25 対象外 }
26 対象外
27 対象外 internal sealed class DynamicParallelNodeView : DynamicObject
28 対象外 {
29 対象外 private readonly IParallelNode _node;
30 対象外 private readonly IParallelNodeInternal _internalNode;
31 対象外 private readonly CompareConfiguration _configuration;
32 対象外
33 実行済み 74 private DynamicParallelNodeView(IParallelNode node, CompareConfiguration configuration)
34 対象外 {
35 実行済み 74 _node = node;
36 実行済み 74 _internalNode = (IParallelNodeInternal)node;
37 実行済み 74 _configuration = configuration;
38 実行済み 74 }
39 対象外
40 対象外 public static object From(IParallelNode node, CompareConfiguration configuration)
41 対象外 {
42 実行済み 74 return new DynamicParallelNodeView(node, configuration);
43 対象外 }
44 対象外
45 対象外 public override bool TryGetMember(GetMemberBinder binder, out object? result)
46 対象外 {
47 実行済み 101 if (binder.Name == "NodeKeyText")
48 対象外 {
49 実行済み 3 result = _node.KeyText;
50 実行済み 3 return true;
51 対象外 }
52 対象外
53 実行済み 98 if (binder.Name == "NodeCount")
54 対象外 {
55 実行済み 3 result = _node.Count;
56 実行済み 3 return true;
57 対象外 }
58 対象外
59 実行済み 95 if (_internalNode.TryGetChildren(binder.Name, out var nodes))
60 対象外 {
61 実行済み 39 result = new DynamicParallelListView(nodes, _configuration);
62 実行済み 39 return true;
63 対象外 }
64 対象外
65 実行済み 56 var property = _internalNode.ModelType.GetProperty(
66 実行済み 56 binder.Name,
67 実行済み 56 BindingFlags.Instance | BindingFlags.Public);
68 実行済み 56 var field = property is null
69 実行済み 56 ? _internalNode.ModelType.GetField(binder.Name, BindingFlags.Instance | BindingFlags.Public)
70 実行済み 56 : null;
71 実行済み 56 if (_internalNode.TryGetMemberNode(binder.Name, out var memberNode) || property is not null || field is not null)
72 対象外 {
73 実行済み 56 result = DynamicParallelValuePathView.FromMember(_node, binder.Name, memberNode, _configuration);
74 実行済み 56 return true;
75 対象外 }
76 対象外
77 対象外 // Keep legacy names for compatibility, but resolve model members first.
78 未実行 0 if (binder.Name == nameof(IParallelNode.KeyText))
79 対象外 {
80 未実行 0 result = _node.KeyText;
81 未実行 0 return true;
82 対象外 }
83 対象外
84 未実行 0 if (binder.Name == nameof(IParallelNode.Count))
85 対象外 {
86 未実行 0 result = _node.Count;
87 未実行 0 return true;
88 対象外 }
89 対象外
90 未実行 0 result = null;
91 未実行 0 return false;
92 対象外 }
93 対象外
94 対象外 public override bool TryInvokeMember(InvokeMemberBinder binder, object?[]? args, out object? result)
95 対象外 {
96 実行済み 5 if (binder.Name == nameof(IParallelNode.GetState) && args is { Length: 1 } && args[0] is int modelIndex)
97 対象外 {
98 実行済み 5 result = _node.GetState(modelIndex);
99 実行済み 5 return true;
100 対象外 }
101 対象外
102 未実行 0 result = null;
103 未実行 0 return false;
104 対象外 }
105 対象外
106 実行済み 1 public override string ToString() => _node.ToString() ?? string.Empty;
107 対象外
108 対象外 public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object? result)
109 対象外 {
110 実行済み 2 if (indexes.Length != 1 || indexes[0] is not int modelIndex)
111 対象外 {
112 未実行 0 result = null;
113 未実行 0 return false;
114 対象外 }
115 対象外
116 実行済み 2 result = _node.GetValue(modelIndex);
117 実行済み 2 return true;
118 対象外 }
119 対象外 }
120 対象外
121 対象外 internal sealed class DynamicParallelListView : DynamicObject, IReadOnlyList<object?>
122 対象外 {
123 対象外 private readonly IReadOnlyList<IParallelNode> _nodes;
124 対象外 private readonly CompareConfiguration _configuration;
125 対象外
126 実行済み 44 internal DynamicParallelListView(IReadOnlyList<IParallelNode> nodes, CompareConfiguration configuration)
127 対象外 {
128 実行済み 44 _nodes = nodes;
129 実行済み 44 _configuration = configuration;
130 実行済み 44 }
131 対象外
132 未実行 0 public int Count => _nodes.Count;
133 対象外
134 対象外 public object? this[int index]
135 対象外 {
136 対象外 get
137 対象外 {
138 未実行 0 ValidateIndex(index);
139 未実行 0 return DynamicParallelNodeView.From(_nodes[index], _configuration);
140 対象外 }
141 対象外 }
142 対象外
143 対象外 public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object? result)
144 対象外 {
145 実行済み 39 if (indexes.Length != 1 || indexes[0] is not int index)
146 対象外 {
147 未実行 0 result = null;
148 未実行 0 return false;
149 対象外 }
150 対象外
151 実行済み 39 ValidateIndex(index);
152 実行済み 37 result = DynamicParallelNodeView.From(_nodes[index], _configuration);
153 実行済み 37 return true;
154 対象外 }
155 対象外
156 対象外 public IEnumerator<object?> GetEnumerator()
157 対象外 {
158 実行済み 70 for (var index = 0; index < _nodes.Count; index++)
159 対象外 {
160 実行済み 24 yield return DynamicParallelNodeView.From(_nodes[index], _configuration);
161 対象外 }
162 実行済み 11 }
163 対象外
164 未実行 0 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
165 対象外
166 対象外 private void ValidateIndex(int index)
167 対象外 {
168 実行済み 39 if (index >= 0 && index < _nodes.Count)
169 対象外 {
170 実行済み 37 return;
171 対象外 }
172 対象外
173 実行済み 2 throw new CompareExecutionException(
174 実行済み 2 CompareIssueCode.ModelIndexOutOfRange,
175 実行済み 2 $"list index '{index}' is out of range for count '{_nodes.Count}'.");
176 対象外 }
177 対象外 }
178 対象外
179 対象外 internal sealed class DynamicParallelValuePathView : DynamicObject
180 対象外 {
181 対象外 private readonly IParallelNode _rootNode;
182 対象外 private readonly IParallelNodeInternal _rootInternalNode;
183 対象外 private readonly string[] _memberPath;
184 対象外 private readonly IParallelNode? _materializedNode;
185 対象外 private readonly IParallelNodeInternal? _materializedInternalNode;
186 対象外 private readonly CompareConfiguration _configuration;
187 対象外
188 実行済み 66 private DynamicParallelValuePathView(
189 実行済み 66 IParallelNode rootNode,
190 実行済み 66 string[] memberPath,
191 実行済み 66 IParallelNode? materializedNode,
192 実行済み 66 CompareConfiguration configuration)
193 対象外 {
194 実行済み 66 _rootNode = rootNode;
195 実行済み 66 _rootInternalNode = (IParallelNodeInternal)rootNode;
196 実行済み 66 _memberPath = memberPath;
197 実行済み 66 _materializedNode = materializedNode;
198 実行済み 66 _materializedInternalNode = materializedNode as IParallelNodeInternal;
199 実行済み 66 _configuration = configuration;
200 実行済み 66 }
201 対象外
202 対象外 public static DynamicParallelValuePathView FromMember(
203 対象外 IParallelNode rootNode,
204 対象外 string memberName,
205 対象外 IParallelNode? materializedNode,
206 対象外 CompareConfiguration configuration)
207 対象外 {
208 実行済み 56 return new DynamicParallelValuePathView(rootNode, [memberName], materializedNode, configuration);
209 対象外 }
210 対象外
211 対象外 public ValueState GetState(int modelIndex)
212 対象外 {
213 実行済み 7 if (_materializedNode is not null)
214 対象外 {
215 実行済み 6 return _materializedNode.GetState(modelIndex);
216 対象外 }
217 対象外
218 実行済み 1 var selectedValue = ResolveValue(modelIndex, out var selectedPresence);
219 実行済み 1 if (selectedPresence == NodePresenceState.Missing)
220 対象外 {
221 未実行 0 return ValueState.Missing;
222 対象外 }
223 対象外
224 実行済み 1 if (_rootNode.Count <= 1)
225 対象外 {
226 未実行 0 return ValueState.Missing;
227 対象外 }
228 対象外
229 実行済み 1 var matched = true;
230 実行済み 4 for (var index = 0; index < _rootNode.Count; index++)
231 対象外 {
232 実行済み 2 if (index == modelIndex)
233 対象外 {
234 対象外 continue;
235 対象外 }
236 対象外
237 実行済み 1 var otherValue = ResolveValue(index, out var otherPresence);
238 実行済み 1 if (otherPresence == NodePresenceState.Missing)
239 対象外 {
240 未実行 0 matched = false;
241 未実行 0 break;
242 対象外 }
243 対象外
244 実行済み 1 if (otherPresence != selectedPresence)
245 対象外 {
246 未実行 0 matched = false;
247 未実行 0 break;
248 対象外 }
249 対象外
250 実行済み 1 if (selectedPresence == NodePresenceState.PresentValue
251 実行済み 1 && !Equals(selectedValue, otherValue))
252 対象外 {
253 実行済み 1 matched = false;
254 実行済み 1 break;
255 対象外 }
256 対象外 }
257 対象外
258 実行済み 1 return ValueStateExtensions.ToComparisonState(hasComparisonTarget: true, matched);
259 対象外 }
260 対象外
261 対象外 public override bool TryGetMember(GetMemberBinder binder, out object? result)
262 対象外 {
263 実行済み 15 if (_materializedNode is not null)
264 対象外 {
265 実行済み 15 if (binder.Name == "NodeKeyText")
266 対象外 {
267 未実行 0 result = _materializedNode.KeyText;
268 未実行 0 return true;
269 対象外 }
270 対象外
271 実行済み 15 if (binder.Name == "NodeCount")
272 対象外 {
273 未実行 0 result = _materializedNode.Count;
274 未実行 0 return true;
275 対象外 }
276 対象外
277 実行済み 15 if (_materializedInternalNode?.TryGetChildren(binder.Name, out var childNodes) == true)
278 対象外 {
279 実行済み 1 result = new DynamicParallelListView(childNodes, _configuration);
280 実行済み 1 return true;
281 対象外 }
282 対象外
283 実行済み 14 if (_materializedInternalNode?.TryGetMemberNode(binder.Name, out var nextMaterializedNode) == true)
284 対象外 {
285 実行済み 9 result = new DynamicParallelValuePathView(_rootNode, [.. _memberPath, binder.Name], nextMaterializedNode, _configuration);
286 実行済み 9 return true;
287 対象外 }
288 対象外
289 実行済み 5 if (binder.Name == nameof(IParallelNode.KeyText))
290 対象外 {
291 未実行 0 result = _materializedNode.KeyText;
292 未実行 0 return true;
293 対象外 }
294 対象外
295 実行済み 5 if (binder.Name == nameof(IParallelNode.Count))
296 対象外 {
297 未実行 0 result = _materializedNode.Count;
298 未実行 0 return true;
299 対象外 }
300 対象外 }
301 対象外
302 実行済み 5 if (TryCreateRuntimeDerivedContainerView(binder.Name, out result))
303 対象外 {
304 実行済み 4 return true;
305 対象外 }
306 対象外
307 実行済み 1 result = new DynamicParallelValuePathView(_rootNode, [.. _memberPath, binder.Name], materializedNode: null, _configuration);
308 実行済み 1 return true;
309 対象外 }
310 対象外
311 対象外 public override bool TryInvokeMember(InvokeMemberBinder binder, object?[]? args, out object? result)
312 対象外 {
313 実行済み 7 if (binder.Name == nameof(GetState) && args is { Length: 1 } && args[0] is int modelIndex)
314 対象外 {
315 実行済み 7 result = GetState(modelIndex);
316 実行済み 7 return true;
317 対象外 }
318 対象外
319 未実行 0 result = null;
320 未実行 0 return false;
321 対象外 }
322 対象外
323 実行済み 1 public override string ToString() => _materializedNode?.ToString() ?? base.ToString() ?? string.Empty;
324 対象外
325 対象外 public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object? result)
326 対象外 {
327 実行済み 43 if (indexes.Length != 1 || indexes[0] is not int modelIndex)
328 対象外 {
329 未実行 0 result = null;
330 未実行 0 return false;
331 対象外 }
332 対象外
333 実行済み 43 result = ResolveValue(modelIndex, out _);
334 実行済み 43 return true;
335 対象外 }
336 対象外
337 対象外 private bool TryCreateRuntimeDerivedContainerView(string memberName, out object? result)
338 対象外 {
339 実行済み 5 var values = new object?[_rootNode.Count];
340 実行済み 5 var states = new NodePresenceState[_rootNode.Count];
341 実行済み 5 Type? containerType = null;
342 対象外
343 実行済み 30 for (var modelIndex = 0; modelIndex < _rootNode.Count; modelIndex++)
344 対象外 {
345 実行済み 10 var currentValue = ResolveValue(modelIndex, out var currentState);
346 実行済み 10 if (currentState == NodePresenceState.Missing)
347 対象外 {
348 未実行 0 values[modelIndex] = null;
349 未実行 0 states[modelIndex] = NodePresenceState.Missing;
350 未実行 0 continue;
351 対象外 }
352 対象外
353 実行済み 10 if (currentState == NodePresenceState.PresentNull || currentValue is null)
354 対象外 {
355 未実行 0 values[modelIndex] = null;
356 未実行 0 states[modelIndex] = NodePresenceState.PresentNull;
357 未実行 0 continue;
358 対象外 }
359 対象外
360 実行済み 10 var currentType = currentValue.GetType();
361 実行済み 10 var property = currentType.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public);
362 実行済み 10 var field = property is null ? currentType.GetField(memberName, BindingFlags.Instance | BindingFlags.Public) : null;
363 実行済み 10 if (property is null && field is null)
364 対象外 {
365 未実行 0 result = null;
366 未実行 0 return false;
367 対象外 }
368 対象外
369 実行済み 10 var memberValue = property is not null ? property.GetValue(currentValue) : field!.GetValue(currentValue);
370 実行済み 10 values[modelIndex] = memberValue;
371 実行済み 10 states[modelIndex] = memberValue is null ? NodePresenceState.PresentNull : NodePresenceState.PresentValue;
372 対象外
373 実行済み 10 var candidateType = memberValue?.GetType() ?? property?.PropertyType ?? field!.FieldType;
374 実行済み 10 if (ParallelCompareApi.IsContainerType(candidateType))
375 対象外 {
376 実行済み 8 containerType ??= candidateType;
377 対象外 }
378 対象外 }
379 対象外
380 実行済み 5 if (containerType is null)
381 対象外 {
382 実行済み 1 result = null;
383 実行済み 1 return false;
384 対象外 }
385 対象外
386 実行済み 4 var path = string.Join('.', [_rootInternalNode.ModelType.Name, .. _memberPath, memberName]);
387 実行済み 4 if (!ParallelCompareApi.TryBuildDynamicContainerChildren(containerType, values, states, path, _configuration, out var childNodes))
388 対象外 {
389 未実行 0 result = null;
390 未実行 0 return false;
391 対象外 }
392 対象外
393 実行済み 4 result = new DynamicParallelListView(childNodes, _configuration);
394 実行済み 4 return true;
395 対象外 }
396 対象外
397 対象外 private object? ResolveValue(int modelIndex, out NodePresenceState state)
398 対象外 {
399 実行済み 55 state = _rootInternalNode.GetPresenceState(modelIndex);
400 実行済み 55 if (state == NodePresenceState.Missing)
401 対象外 {
402 実行済み 4 return null;
403 対象外 }
404 対象外
405 実行済み 51 object? current = _rootNode.GetValue(modelIndex);
406 実行済み 51 if (current is null)
407 対象外 {
408 未実行 0 state = NodePresenceState.PresentNull;
409 未実行 0 return null;
410 対象外 }
411 対象外
412 実行済み 213 foreach (var memberName in _memberPath)
413 対象外 {
414 実行済み 56 var currentType = current.GetType();
415 実行済み 56 var property = currentType.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public);
416 実行済み 56 var field = property is null ? currentType.GetField(memberName, BindingFlags.Instance | BindingFlags.Public) : null;
417 実行済み 56 if (property is null && field is null)
418 対象外 {
419 未実行 0 throw new MissingMemberException(
420 未実行 0 current.GetType().FullName,
421 未実行 0 memberName);
422 対象外 }
423 対象外
424 実行済み 56 current = property is not null ? property.GetValue(current) : field!.GetValue(current);
425 実行済み 56 if (current is null)
426 対象外 {
427 実行済み 1 state = NodePresenceState.PresentNull;
428 実行済み 1 return null;
429 対象外 }
430 対象外 }
431 対象外
432 実行済み 50 state = NodePresenceState.PresentValue;
433 実行済み 50 return current;
434 対象外 }
435 対象外 }