Skip to content

Commit 5f69faa

Browse files
author
Michael Jin
authored
Add support for generating the method and generic method comment signature with nested types (#801)
* Add support for generating the method and generic method comment signature with nested types from Xiao Luo * Use type.GenericParameters.Count instead of custom method
1 parent a0a6ce4 commit 5f69faa

File tree

2 files changed

+321
-141
lines changed

2 files changed

+321
-141
lines changed

rocks/Mono.Cecil.Rocks/DocCommentId.cs

+152-68
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@
1010

1111
using System;
1212
using System.Collections.Generic;
13+
using System.Linq;
1314
using System.Text;
1415

1516
namespace Mono.Cecil.Rocks {
1617

17-
public class DocCommentId
18-
{
18+
public class DocCommentId {
19+
IMemberDefinition commentMember;
1920
StringBuilder id;
2021

21-
DocCommentId ()
22+
DocCommentId (IMemberDefinition member)
2223
{
24+
commentMember = member;
2325
id = new StringBuilder ();
2426
}
2527

@@ -87,54 +89,66 @@ void WriteParameters (IList<ParameterDefinition> parameters)
8789

8890
void WriteTypeSignature (TypeReference type)
8991
{
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))
106108
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;
126129
}
127130
}
128131

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+
129140
void WriteGenericInstanceTypeSignature (GenericInstanceType type)
130141
{
131142
if (type.ElementType.IsTypeSpecification ())
132143
throw new NotSupportedException ();
133144

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);
138152
}
139153

140154
void WriteList<T> (IList<T> list, Action<T> action)
@@ -197,10 +211,15 @@ void WriteDefinition (char id, IMemberDefinition member)
197211
WriteItemName (member.Name);
198212
}
199213

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)
201220
{
202221
if (type.DeclaringType != null) {
203-
WriteTypeFullName (type.DeclaringType);
222+
WriteTypeFullName (type.DeclaringType, options);
204223
id.Append ('.');
205224
}
206225

@@ -211,18 +230,69 @@ void WriteTypeFullName (TypeReference type, bool stripGenericArity = false)
211230

212231
var name = type.Name;
213232

214-
if (stripGenericArity) {
233+
if (options.IsArgument) {
215234
var index = name.LastIndexOf ('`');
216235
if (index > 0)
217236
name = name.Substring (0, index);
218237
}
219238

220239
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;
221267
}
222268

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+
223293
void WriteItemName (string name)
224294
{
225-
id.Append (name.Replace ('.', '#').Replace('<', '{').Replace('>', '}'));
295+
id.Append (name.Replace('.', '#').Replace('<', '{').Replace('>', '}'));
226296
}
227297

228298
public override string ToString ()
@@ -235,30 +305,44 @@ public static string GetDocCommentId (IMemberDefinition member)
235305
if (member == null)
236306
throw new ArgumentNullException ("member");
237307

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);
259328
}
260329

261330
return documentId.ToString ();
262331
}
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+
}
263347
}
264-
}
348+
}

0 commit comments

Comments
 (0)