@@ -25,14 +25,14 @@ public AnnotationResolver(PipelineResult pipelineResult)
25
25
26
26
/// <summary>
27
27
/// Attempt to retrieve the <paramref name="symbol"/>'s value for the annotation <paramref name="id"/>. This will check any
28
- /// annotation providers that were passed to the constructor , and the internal per-symbol annotation storage.
28
+ /// annotation providers that were passed to the resolver , and the internal per-symbol annotation storage.
29
29
/// </summary>
30
30
/// <typeparam name="TValue">
31
31
/// The expected type of the annotation value. If the type does not match, a <see cref="AnnotationTypeException"/> will be thrown.
32
32
/// If the annotation allows multiple types for its values, and a type parameter cannot be determined statically,
33
- /// use <see cref="TryGetAnnotation (CliSymbol, AnnotationId, out object?)"/> to access the annotation value without checking its type.
33
+ /// use <see cref="TryGet (CliSymbol, AnnotationId, out object?)"/> to access the annotation value without checking its type.
34
34
/// </typeparam>
35
- /// <param name="symbol">The symbol the value is attached to </param>
35
+ /// <param name="symbol">The symbol that is annotated </param>
36
36
/// <param name="id">
37
37
/// The identifier for the annotation value to be retrieved.
38
38
/// For example, the annotation identifier for the help description is <see cref="HelpAnnotations.Description">.
@@ -69,9 +69,9 @@ public bool TryGet<TValue>(CliSymbol symbol, AnnotationId annotationId, [NotNull
69
69
70
70
/// <summary>
71
71
/// Attempt to retrieve the <paramref name="symbol"/>'s value for the annotation <paramref name="id"/>. This will check any
72
- /// annotation providers that were passed to the constructor , and the internal per-symbol annotation storage.
72
+ /// annotation providers that were passed to the resolver , and the internal per-symbol annotation storage.
73
73
/// </summary>
74
- /// <param name="symbol">The symbol the value is attached to </param>
74
+ /// <param name="symbol">The symbol that is annotated </param>
75
75
/// <param name="id">
76
76
/// The identifier for the annotation value to be retrieved.
77
77
/// For example, the annotation identifier for the help description is <see cref="HelpAnnotations.Description">.
@@ -90,6 +90,13 @@ public bool TryGet<TValue>(CliSymbol symbol, AnnotationId annotationId, [NotNull
90
90
/// </remarks>
91
91
public bool TryGet ( CliSymbol symbol , AnnotationId annotationId , [ NotNullWhen ( true ) ] out object ? value )
92
92
{
93
+ // a value set directly on the symbol takes precedence over values returned by providers.
94
+ if ( symbol . TryGetAnnotation ( annotationId , out value ) )
95
+ {
96
+ return true ;
97
+ }
98
+
99
+ // Providers are given precedence in the order they were provided to the resolver.
93
100
foreach ( var provider in providers )
94
101
{
95
102
if ( provider . TryGet ( symbol , annotationId , context , out value ) )
@@ -98,7 +105,7 @@ public bool TryGet(CliSymbol symbol, AnnotationId annotationId, [NotNullWhen(tru
98
105
}
99
106
}
100
107
101
- return symbol . TryGetAnnotation ( annotationId , out value ) ;
108
+ return false ;
102
109
}
103
110
104
111
/// <summary>
@@ -128,4 +135,60 @@ public bool TryGet(CliSymbol symbol, AnnotationId annotationId, [NotNullWhen(tru
128
135
129
136
return default ;
130
137
}
138
+
139
+ /// <summary>
140
+ /// For an annotation <paramref name="id"/> that permits multiple values, enumerate the values associated with
141
+ /// the <paramref name="symbol"/>. If the annotation is not set, an empty enumerable will be returned. This will
142
+ /// check any annotation providers that were passed to the resolver, and the internal per-symbol annotation storage.
143
+ /// </summary>
144
+ /// <typeparam name="TValue">
145
+ /// The expected type of the annotation value. If the type does not match, a <see cref="AnnotationCollectionTypeException"/>
146
+ /// will be thrown.
147
+ /// </typeparam>
148
+ /// <param name="symbol">The symbol that is annotated</param>
149
+ /// <param name="id">
150
+ /// The identifier for the annotation value to be retrieved.
151
+ /// For example, the annotation identifier for the help description is <see cref="HelpAnnotations.Description">.
152
+ /// </param>
153
+ /// <param name="value">An out parameter to contain the result</param>
154
+ /// <returns>True if successful</returns>
155
+ /// <remarks>
156
+ /// This is intended for use by developers defining custom annotation IDs. Anyone defining an annotation
157
+ /// ID should also define an accessor extension method on <see cref="AnnotationResolver"/> extension method
158
+ /// on <see cref="CliSymbol"/> that subsystem authors can use to access the annotation value, such as
159
+ /// <see cref="HelpAnnotationExtensions.GetDescription{TSymbol}(AnnotationResolver, TSymbol)"/>.
160
+ /// </remarks>
161
+ public IEnumerable < TValue > Enumerate < TValue > ( CliSymbol symbol , AnnotationId annotationId )
162
+ {
163
+ // Values added directly on the symbol take precedence over values returned by providers,
164
+ // so they are returned first.
165
+ // NOTE: EnumerateAnnotations returns these in the reverse order they were added, which means that
166
+ // callers that take the first value of a given subtype will get the most recently added value of
167
+ // that subtype that the CLI author added to the symbol.
168
+ foreach ( var value in symbol . EnumerateAnnotations < TValue > ( annotationId ) )
169
+ {
170
+ yield return value ;
171
+ }
172
+
173
+ // Providers are given precedence in the order they were provided to the resolver.
174
+ foreach ( var provider in providers )
175
+ {
176
+ if ( ! provider . TryGet ( symbol , annotationId , context , out object ? rawValue ) )
177
+ {
178
+ continue ;
179
+ }
180
+
181
+ if ( rawValue is IEnumerable < TValue > expectedTypeValue )
182
+ {
183
+ foreach ( var value in expectedTypeValue )
184
+ {
185
+ yield return value ;
186
+ }
187
+ }
188
+ else
189
+ {
190
+ throw new AnnotationTypeException ( annotationId , typeof ( IEnumerable < TValue > ) , rawValue ? . GetType ( ) , provider ) ;
191
+ }
192
+ }
193
+ }
131
194
}
0 commit comments