Skip to content
← Back

src/semantic/dotnet/tuple_element_names.ghul

1
namespace Semantic.DotNet is
2
use Collections;
3
4
use ATTRIBUTE_DATA = System.Reflection.CustomAttributeData;
5
use TYPED_ARGUMENT = System.Reflection.CustomAttributeTypedArgument;
6
7
use Ghul.Pipes;
8
9
// Reads `System.Runtime.CompilerServices.TupleElementNamesAttribute`
10
// — the standard .NET carrier for tuple element names — off the
11
// custom attributes of a reflected member, parameter, field or
12
// property. The `ValueTuple` type itself holds no names, so a
13
// reflected tuple needs this to recover the names a C# (or ghūl)
14
// producer recorded at the declaration site.
15
class TUPLE_ELEMENT_NAMES is
16
// The flattened element-name array declared by a
17
// TupleElementNamesAttribute among `attributes`, or null when
18
// there is none. A null entry marks an unnamed element.
19
read(attributes: Iterable[ATTRIBUTE_DATA]?) -> List[string?]? static is
20
if !attributes? then
21
return null;
22
fi
23
24
try
25
for attribute in attributes do
26
let attribute_type = attribute.attribute_type;
27
28
if
29
attribute_type.full_name =~ "System.Runtime.CompilerServices.TupleElementNamesAttribute"
30
then
31
for constructor_argument in attribute.constructor_arguments do
32
return _read_names(constructor_argument);
33
od
34
fi
35
od
36
catch ex: System.Exception
37
yrt
38
39
return null;
40
si
41
42
// The single `string[]` constructor argument surfaces as a
43
// collection of CustomAttributeTypedArgument, one per element.
44
_read_names(argument: TYPED_ARGUMENT) -> List[string?]? static is
45
let elements = cast Iterable[TYPED_ARGUMENT]?(argument.value);
46
47
if !elements? then
48
return null;
49
fi
50
51
let result = LIST[string]();
52
53
for element in elements do
54
result.add(cast string?(element.value)!);
55
od
56
57
return result;
58
si
59
60
// The `.custom` directive carrying `type`'s element names, or
61
// null when `type` is not a named flat tuple. A nested tuple
62
// needs the full flattened name array, which is not modelled
63
// here — leave it unnamed rather than emit a shape a C# reader
64
// would misinterpret.
65
gen_attribute_line_for_type(type: Types.Type) -> string? static is
66
if !type.is_value_tuple then
67
return null;
68
fi
69
70
let names = type.tuple_element_names;
71
72
if !names? \/ !(names |> any(name => name?)) then
73
return null;
74
fi
75
76
for argument in type.arguments do
77
if argument.is_value_tuple then
78
return null;
79
fi
80
od
81
82
return
83
".custom instance void [System.Runtime]System.Runtime.CompilerServices.TupleElementNamesAttribute::.ctor(string[]) = {gen_attribute_arguments(names)}";
84
si
85
86
// The arguments for `TupleElementNamesAttribute::.ctor(string[])`
87
// carrying `names`. A null entry marks an unnamed element.
88
gen_attribute_arguments(names: List[string?]) -> string static =>
89
"{{ {IL_ATTRIBUTE_ARGUMENTS.string_array_argument(names)} }}";
90
si
91
si