2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
4
using System . Collections . Concurrent ;
5
- using System . Collections . Generic ;
6
- using System . Collections . Specialized ;
7
5
using System . Diagnostics ;
8
6
using System . Diagnostics . CodeAnalysis ;
9
- using System . Reflection ;
10
7
using DiffPlex . DiffBuilder ;
11
8
using DiffPlex . DiffBuilder . Model ;
12
9
using Microsoft . CodeAnalysis ;
@@ -305,7 +302,7 @@ private static string GetFinalAssemblyDiff(string assemblyName, string diffText)
305
302
return sb . ToString ( ) ;
306
303
}
307
304
308
- private static ConcurrentDictionary < string , MemberDeclarationSyntax > CollectChildrenNodes ( SyntaxNode ? parentNode , SemanticModel ? model )
305
+ private ConcurrentDictionary < string , MemberDeclarationSyntax > CollectChildrenNodes ( SyntaxNode ? parentNode , SemanticModel ? model )
309
306
{
310
307
if ( parentNode == null )
311
308
{
@@ -521,7 +518,7 @@ private Dictionary<string, AttributeSyntax> CollectAttributeNodes(MemberDeclarat
521
518
continue ;
522
519
}
523
520
var realAttributeNode = attributeNode . WithArgumentList ( attributeNode . ArgumentList ) ;
524
- if ( ! dictionary . TryAdd ( realAttributeNode . ToFullString ( ) , realAttributeNode ) )
521
+ if ( ! dictionary . TryAdd ( GetAttributeDocId ( realAttributeNode , model ) , realAttributeNode ) )
525
522
{
526
523
_log . LogWarning ( string . Format ( Resources . AttributeAlreadyExists , realAttributeNode . ToFullString ( ) , GetDocId ( memberNode , model ) ) ) ;
527
524
}
@@ -650,7 +647,33 @@ private static IEnumerable<T> GetMembersOfType<T>(SyntaxNode node) where T : Mem
650
647
. Where ( n => n is T m && IsEnumMemberOrHasPublicOrProtectedModifierOrIsDestructor ( m ) )
651
648
. Cast < T > ( ) ;
652
649
653
- private static string GetDocId ( SyntaxNode node , SemanticModel model )
650
+ private string GetAttributeDocId ( AttributeSyntax attribute , SemanticModel model )
651
+ {
652
+ string ? attributeDocId = null ;
653
+ if ( attribute . ArgumentList is AttributeArgumentListSyntax list && list . Arguments . Any ( ) )
654
+ {
655
+ // Workaround to ensure that repeated attributes with different arguments are all included
656
+ attributeDocId = attribute . ToFullString ( ) ;
657
+ }
658
+ else if ( model . GetSymbolInfo ( attribute ) . Symbol is IMethodSymbol constructor )
659
+ {
660
+ try
661
+ {
662
+ attributeDocId = constructor . ContainingType . GetDocumentationCommentId ( ) ;
663
+ }
664
+ catch ( Exception e )
665
+ {
666
+ _log . LogWarning ( e . Message ) ;
667
+ }
668
+ }
669
+ // Workaround because some rare cases of attributes in WinForms like System.Windows.Markup.ContentPropertyAttribute
670
+ // cannot be found in the current model.
671
+ attributeDocId ??= attribute . ToFullString ( ) ;
672
+
673
+ return attributeDocId ;
674
+ }
675
+
676
+ private string GetDocId ( SyntaxNode node , SemanticModel model )
654
677
{
655
678
ISymbol ? symbol = node switch
656
679
{
@@ -660,7 +683,7 @@ private static string GetDocId(SyntaxNode node, SemanticModel model)
660
683
EventFieldDeclarationSyntax eventFieldDeclaration => model . GetDeclaredSymbol ( eventFieldDeclaration . Declaration . Variables . First ( ) ) ,
661
684
PropertyDeclarationSyntax propertyDeclaration => model . GetDeclaredSymbol ( propertyDeclaration ) ,
662
685
_ => model . GetDeclaredSymbol ( node )
663
- } ;
686
+ } ;
664
687
665
688
if ( symbol ? . GetDocumentationCommentId ( ) is string docId )
666
689
{
0 commit comments