@@ -25,6 +25,7 @@ private static class DocElementNames
25
25
public static readonly XName Members = XName . Get ( "members" ) ;
26
26
public static readonly XName Param = XName . Get ( "param" ) ;
27
27
public static readonly XName TypeParam = XName . Get ( "typeparam" ) ;
28
+ public static readonly XName TypeParamRef = XName . Get ( "typeparamref" ) ;
28
29
public static readonly XName Overloads = XName . Get ( "overloads" ) ;
29
30
public static readonly XName Redirect = XName . Get ( "redirect" ) ;
30
31
public static readonly XName Returns = XName . Get ( "returns" ) ;
@@ -338,27 +339,54 @@ static void removeDoc(List<XNode> nodes, int pos)
338
339
continue ;
339
340
340
341
var ename = elem . Name ;
342
+ string ? pname = ( string ) elem . Attribute ( DocAttributeNames . Name ) ;
341
343
342
344
if ( ename == DocElementNames . Returns && ! dm . HasReturn || ename == DocElementNames . Value && ! dm . HasValue )
343
345
{
344
346
removeDoc ( nodes , i ) ;
345
347
continue ;
346
348
}
347
349
348
- if ( ename == DocElementNames . Param || ename == DocElementNames . TypeParam )
350
+ if ( ename == DocElementNames . Param )
349
351
{
350
- string ? pname = ( string ) elem . Attribute ( DocAttributeNames . Name ) ;
351
- var pmap = ename == DocElementNames . Param ? dm . ParamMap : dm . TypeParamMap ;
352
-
353
- if ( ! pmap . ContainsKey ( pname ) )
352
+ if ( ! dm . ParamMap . ContainsKey ( pname ) )
354
353
{
355
354
removeDoc ( nodes , i ) ;
356
355
continue ;
357
356
}
358
357
359
- elem . SetAttributeValue ( DocAttributeNames . Name , pmap [ pname ] ) ;
358
+ elem . SetAttributeValue ( DocAttributeNames . Name , dm . ParamMap [ pname ] ) ;
360
359
foreach ( var pref in nodes . OfType < XElement > ( ) . DescendantNodesAndSelf ( ) . OfType < XElement > ( ) . Where ( e => e . Name == ( ename . LocalName + "ref" ) && ( string ) e . Attribute ( DocAttributeNames . Name ) == pname ) )
361
- pref . SetAttributeValue ( DocAttributeNames . Name , pmap [ pname ] ) ;
360
+ pref . SetAttributeValue ( DocAttributeNames . Name , dm . ParamMap [ pname ] ) ;
361
+ }
362
+
363
+ if ( ename == DocElementNames . TypeParam )
364
+ {
365
+ if ( ! dm . TypeParamMap . ContainsKey ( pname ) || dm . TypeParamMap [ pname ] is not GenericParameter )
366
+ {
367
+ removeDoc ( nodes , i ) ;
368
+ continue ;
369
+ }
370
+
371
+ elem . SetAttributeValue ( DocAttributeNames . Name , dm . TypeParamMap [ pname ] . Name ) ;
372
+ }
373
+
374
+ foreach ( var tpr in elem . Descendants ( DocElementNames . TypeParamRef ) . ToList ( ) )
375
+ {
376
+ if ( ! tpr . HasAttribute ( DocAttributeNames . Name ) || ! dm . TypeParamMap . ContainsKey ( ( string ) tpr . Attribute ( DocAttributeNames . Name ) ) )
377
+ {
378
+ if ( ( tpr . PreviousNode ? . IsWhiteSpace ( ) ) . GetValueOrDefault ( ) )
379
+ tpr . PreviousNode ! . Remove ( ) ;
380
+
381
+ tpr . Remove ( ) ;
382
+ continue ;
383
+ }
384
+
385
+ var tr = dm . TypeParamMap [ ( string ) tpr . Attribute ( DocAttributeNames . Name ) ] ;
386
+ if ( tr . IsGenericParameter )
387
+ tpr . SetAttributeValue ( DocAttributeNames . Name , tr . Name ) ;
388
+ else
389
+ tpr . ReplaceWith ( new XElement ( "see" , new XAttribute ( "cref" , tr . GetDocID ( ) ) ) ) ;
362
390
}
363
391
364
392
// Doc inheritance rules built for compatibility with SHFB modulo the name change of the "select" attribute to "path"
@@ -504,36 +532,16 @@ private static string getTypeIDFromDocID(string docID)
504
532
private class DocMatch ( string cref )
505
533
{
506
534
private static readonly IReadOnlyDictionary < string , string > emptyMap = new Dictionary < string , string > ( ) ;
535
+ private static readonly IReadOnlyDictionary < string , TypeReference > emptyTypeMap = new Dictionary < string , TypeReference > ( ) ;
507
536
508
537
public string Cref = cref ;
509
- public IReadOnlyDictionary < string , string > TypeParamMap = emptyMap ;
510
538
public IReadOnlyDictionary < string , string > ParamMap = emptyMap ;
539
+ public IReadOnlyDictionary < string , TypeReference > TypeParamMap = emptyTypeMap ;
511
540
public bool HasReturn = false ;
512
541
public bool HasValue = false ;
513
542
514
- public DocMatch ( string cref , TypeReference t , TypeReference ? bt = null ) : this ( cref )
515
- {
516
- if ( t . HasGenericParameters && ( bt ? . IsGenericInstance ?? true ) )
517
- {
518
- var tpm = new Dictionary < string , string > ( ) ;
519
-
520
- if ( bt is not null )
521
- {
522
- var ga = ( ( GenericInstanceType ) bt ) . GenericArguments ;
523
- var rbt = bt . Resolve ( ) ;
524
-
525
- foreach ( var tp in t . GenericParameters . Where ( ga . Contains ) )
526
- tpm . Add ( rbt . GenericParameters [ ga . IndexOf ( tp ) ] . Name , tp . Name ) ;
527
- }
528
- else
529
- {
530
- foreach ( var tp in t . GenericParameters )
531
- tpm . Add ( tp . Name , tp . Name ) ;
532
- }
533
-
534
- TypeParamMap = tpm ;
535
- }
536
- }
543
+ public DocMatch ( string cref , TypeDefinition t , TypeReference ? bt = null ) : this ( cref ) =>
544
+ TypeParamMap = t . GetTypeParamMap ( bt ? . Resolve ( ) ) ?? emptyTypeMap ;
537
545
538
546
public DocMatch ( string cref , MethodDefinition m , MethodDefinition ? bm = null ) : this ( cref )
539
547
{
@@ -546,14 +554,14 @@ public DocMatch(string cref, MethodDefinition m, MethodDefinition? bm = null) :
546
554
ParamMap = pm ;
547
555
}
548
556
557
+ var tpm = m . DeclaringType . GetTypeParamMap ( bm ? . DeclaringType ) ;
549
558
if ( m . HasGenericParameters )
550
559
{
551
- var tpm = new Dictionary < string , string > ( ) ;
560
+ tpm ??= [ ] ;
552
561
foreach ( var tp in m . GenericParameters )
553
- tpm . Add ( bm ? . GenericParameters [ tp . Position ] . Name ?? tp . Name , tp . Name ) ;
554
-
555
- TypeParamMap = tpm ;
562
+ tpm [ bm ? . GenericParameters [ tp . Position ] . Name ?? tp . Name ] = tp ;
556
563
}
564
+ TypeParamMap = tpm ?? emptyTypeMap ;
557
565
558
566
HasReturn = m . HasReturnValue ( ) ;
559
567
HasValue = m . IsPropertyMethod ( ) ;
0 commit comments