10
10
11
11
using System ;
12
12
using System . Collections . Generic ;
13
+ using System . Linq ;
13
14
using System . Text ;
14
15
15
16
namespace Mono . Cecil . Rocks {
16
17
17
- public class DocCommentId
18
- {
18
+ public class DocCommentId {
19
+ IMemberDefinition commentMember ;
19
20
StringBuilder id ;
20
21
21
- DocCommentId ( )
22
+ DocCommentId ( IMemberDefinition member )
22
23
{
24
+ commentMember = member ;
23
25
id = new StringBuilder ( ) ;
24
26
}
25
27
@@ -87,54 +89,66 @@ void WriteParameters (IList<ParameterDefinition> parameters)
87
89
88
90
void WriteTypeSignature ( TypeReference type )
89
91
{
90
- switch ( type . MetadataType )
91
- {
92
- case MetadataType . Array :
93
- WriteArrayTypeSignature ( ( ArrayType ) type ) ;
94
- break ;
95
- case MetadataType . ByReference :
96
- WriteTypeSignature ( ( ( ByReferenceType ) type ) . ElementType ) ;
97
- id . Append ( '@' ) ;
98
- break ;
99
- case MetadataType . FunctionPointer :
100
- WriteFunctionPointerTypeSignature ( ( FunctionPointerType ) type ) ;
101
- break ;
102
- case MetadataType . GenericInstance :
103
- WriteGenericInstanceTypeSignature ( ( GenericInstanceType ) type ) ;
104
- break ;
105
- case MetadataType . Var :
92
+ switch ( type . MetadataType ) {
93
+ case MetadataType . Array :
94
+ WriteArrayTypeSignature ( ( ArrayType ) type ) ;
95
+ break ;
96
+ case MetadataType . ByReference :
97
+ WriteTypeSignature ( ( ( ByReferenceType ) type ) . ElementType ) ;
98
+ id . Append ( '@' ) ;
99
+ break ;
100
+ case MetadataType . FunctionPointer :
101
+ WriteFunctionPointerTypeSignature ( ( FunctionPointerType ) type ) ;
102
+ break ;
103
+ case MetadataType . GenericInstance :
104
+ WriteGenericInstanceTypeSignature ( ( GenericInstanceType ) type ) ;
105
+ break ;
106
+ case MetadataType . Var :
107
+ if ( IsGenericMethodTypeParameter ( type ) )
106
108
id . Append ( '`' ) ;
107
- id . Append ( ( ( GenericParameter ) type ) . Position ) ;
108
- break ;
109
- case MetadataType . MVar :
110
- id . Append ( '`' ) . Append ( '`' ) ;
111
- id . Append ( ( ( GenericParameter ) type ) . Position ) ;
112
- break ;
113
- case MetadataType . OptionalModifier :
114
- WriteModiferTypeSignature ( ( OptionalModifierType ) type , '!' ) ;
115
- break ;
116
- case MetadataType . RequiredModifier :
117
- WriteModiferTypeSignature ( ( RequiredModifierType ) type , '|' ) ;
118
- break ;
119
- case MetadataType . Pointer :
120
- WriteTypeSignature ( ( ( PointerType ) type ) . ElementType ) ;
121
- id . Append ( '*' ) ;
122
- break ;
123
- default :
124
- WriteTypeFullName ( type ) ;
125
- break ;
109
+ id . Append ( '`' ) ;
110
+ id . Append ( ( ( GenericParameter ) type ) . Position ) ;
111
+ break ;
112
+ case MetadataType . MVar :
113
+ id . Append ( '`' ) . Append ( '`' ) ;
114
+ id . Append ( ( ( GenericParameter ) type ) . Position ) ;
115
+ break ;
116
+ case MetadataType . OptionalModifier :
117
+ WriteModiferTypeSignature ( ( OptionalModifierType ) type , '!' ) ;
118
+ break ;
119
+ case MetadataType . RequiredModifier :
120
+ WriteModiferTypeSignature ( ( RequiredModifierType ) type , '|' ) ;
121
+ break ;
122
+ case MetadataType . Pointer :
123
+ WriteTypeSignature ( ( ( PointerType ) type ) . ElementType ) ;
124
+ id . Append ( '*' ) ;
125
+ break ;
126
+ default :
127
+ WriteTypeFullName ( type ) ;
128
+ break ;
126
129
}
127
130
}
128
131
132
+ bool IsGenericMethodTypeParameter ( TypeReference type )
133
+ {
134
+ if ( commentMember is MethodDefinition methodDefinition && type is GenericParameter genericParameter )
135
+ return methodDefinition . GenericParameters . Any ( i => i . Name == genericParameter . Name ) ;
136
+
137
+ return false ;
138
+ }
139
+
129
140
void WriteGenericInstanceTypeSignature ( GenericInstanceType type )
130
141
{
131
142
if ( type . ElementType . IsTypeSpecification ( ) )
132
143
throw new NotSupportedException ( ) ;
133
144
134
- WriteTypeFullName ( type . ElementType , stripGenericArity : true ) ;
135
- id . Append ( '{' ) ;
136
- WriteList ( type . GenericArguments , WriteTypeSignature ) ;
137
- id . Append ( '}' ) ;
145
+ GenericTypeOptions options = new GenericTypeOptions {
146
+ IsArgument = true ,
147
+ IsNestedType = type . IsNested ,
148
+ Arguments = type . GenericArguments
149
+ } ;
150
+
151
+ WriteTypeFullName ( type . ElementType , options ) ;
138
152
}
139
153
140
154
void WriteList < T > ( IList < T > list , Action < T > action )
@@ -197,10 +211,15 @@ void WriteDefinition (char id, IMemberDefinition member)
197
211
WriteItemName ( member . Name ) ;
198
212
}
199
213
200
- void WriteTypeFullName ( TypeReference type , bool stripGenericArity = false )
214
+ void WriteTypeFullName ( TypeReference type )
215
+ {
216
+ WriteTypeFullName ( type , GenericTypeOptions . Empty ( ) ) ;
217
+ }
218
+
219
+ void WriteTypeFullName ( TypeReference type , GenericTypeOptions options )
201
220
{
202
221
if ( type . DeclaringType != null ) {
203
- WriteTypeFullName ( type . DeclaringType ) ;
222
+ WriteTypeFullName ( type . DeclaringType , options ) ;
204
223
id . Append ( '.' ) ;
205
224
}
206
225
@@ -211,18 +230,69 @@ void WriteTypeFullName (TypeReference type, bool stripGenericArity = false)
211
230
212
231
var name = type . Name ;
213
232
214
- if ( stripGenericArity ) {
233
+ if ( options . IsArgument ) {
215
234
var index = name . LastIndexOf ( '`' ) ;
216
235
if ( index > 0 )
217
236
name = name . Substring ( 0 , index ) ;
218
237
}
219
238
220
239
id . Append ( name ) ;
240
+
241
+ WriteGenericTypeParameters ( type , options ) ;
242
+ }
243
+
244
+ void WriteGenericTypeParameters ( TypeReference type , GenericTypeOptions options )
245
+ {
246
+ if ( options . IsArgument && IsGenericType ( type ) ) {
247
+ id . Append ( '{' ) ;
248
+ WriteList ( GetGenericTypeArguments ( type , options ) , WriteTypeSignature ) ;
249
+ id . Append ( '}' ) ;
250
+ }
251
+ }
252
+
253
+ static bool IsGenericType ( TypeReference type )
254
+ {
255
+ // When the type is a nested type and that is defined in a generic class,
256
+ // the nested type will have generic parameters but sometimes that is not a generic type.
257
+ if ( type . HasGenericParameters ) {
258
+ var name = string . Empty ;
259
+ var index = type . Name . LastIndexOf ( '`' ) ;
260
+ if ( index >= 0 )
261
+ name = type . Name . Substring ( 0 , index ) ;
262
+
263
+ return type . Name . LastIndexOf ( '`' ) == name . Length ;
264
+ }
265
+
266
+ return false ;
221
267
}
222
268
269
+ IList < TypeReference > GetGenericTypeArguments ( TypeReference type , GenericTypeOptions options )
270
+ {
271
+ if ( options . IsNestedType ) {
272
+ var typeParameterCount = type . GenericParameters . Count ;
273
+ var typeGenericArguments = options . Arguments . Skip ( options . ArgumentIndex ) . Take ( typeParameterCount ) . ToList ( ) ;
274
+
275
+ options . ArgumentIndex += typeParameterCount ;
276
+
277
+ return typeGenericArguments ;
278
+ }
279
+
280
+ return options . Arguments ;
281
+ }
282
+
283
+ //int GetGenericTypeParameterCount (TypeReference type)
284
+ //{
285
+ // var returnValue = 0;
286
+ // var index = type.Name.LastIndexOf ('`');
287
+ // if (index >= 0)
288
+ // returnValue = int.Parse (type.Name.Substring (index + 1));
289
+
290
+ // return returnValue;
291
+ //}
292
+
223
293
void WriteItemName ( string name )
224
294
{
225
- id . Append ( name . Replace ( '.' , '#' ) . Replace ( '<' , '{' ) . Replace ( '>' , '}' ) ) ;
295
+ id . Append ( name . Replace ( '.' , '#' ) . Replace ( '<' , '{' ) . Replace ( '>' , '}' ) ) ;
226
296
}
227
297
228
298
public override string ToString ( )
@@ -235,30 +305,44 @@ public static string GetDocCommentId (IMemberDefinition member)
235
305
if ( member == null )
236
306
throw new ArgumentNullException ( "member" ) ;
237
307
238
- var documentId = new DocCommentId ( ) ;
239
-
240
- switch ( member . MetadataToken . TokenType )
241
- {
242
- case TokenType . Field :
243
- documentId . WriteField ( ( FieldDefinition ) member ) ;
244
- break ;
245
- case TokenType . Method :
246
- documentId . WriteMethod ( ( MethodDefinition ) member ) ;
247
- break ;
248
- case TokenType . TypeDef :
249
- documentId . WriteType ( ( TypeDefinition ) member ) ;
250
- break ;
251
- case TokenType . Event :
252
- documentId . WriteEvent ( ( EventDefinition ) member ) ;
253
- break ;
254
- case TokenType . Property :
255
- documentId . WriteProperty ( ( PropertyDefinition ) member ) ;
256
- break ;
257
- default :
258
- throw new NotSupportedException ( member . FullName ) ;
308
+ var documentId = new DocCommentId ( member ) ;
309
+
310
+ switch ( member . MetadataToken . TokenType ) {
311
+ case TokenType . Field :
312
+ documentId . WriteField ( ( FieldDefinition ) member ) ;
313
+ break ;
314
+ case TokenType . Method :
315
+ documentId . WriteMethod ( ( MethodDefinition ) member ) ;
316
+ break ;
317
+ case TokenType . TypeDef :
318
+ documentId . WriteType ( ( TypeDefinition ) member ) ;
319
+ break ;
320
+ case TokenType . Event :
321
+ documentId . WriteEvent ( ( EventDefinition ) member ) ;
322
+ break ;
323
+ case TokenType . Property :
324
+ documentId . WriteProperty ( ( PropertyDefinition ) member ) ;
325
+ break ;
326
+ default :
327
+ throw new NotSupportedException ( member . FullName ) ;
259
328
}
260
329
261
330
return documentId . ToString ( ) ;
262
331
}
332
+
333
+ class GenericTypeOptions {
334
+ public bool IsArgument { get ; set ; }
335
+
336
+ public bool IsNestedType { get ; set ; }
337
+
338
+ public IList < TypeReference > Arguments { get ; set ; }
339
+
340
+ public int ArgumentIndex { get ; set ; }
341
+
342
+ public static GenericTypeOptions Empty ( )
343
+ {
344
+ return new GenericTypeOptions ( ) ;
345
+ }
346
+ }
263
347
}
264
- }
348
+ }
0 commit comments