@@ -37,8 +37,6 @@ public Lines Build(CompositionCode composition)
3737 var lines = new Lines ( ) ;
3838 lines . AppendLine ( "---" ) ;
3939 lines . AppendLine ( " config:" ) ;
40- lines . AppendLine ( $ " maxTextSize: { int . MaxValue } ") ;
41- lines . AppendLine ( $ " maxEdges: { int . MaxValue } ") ;
4240 lines . AppendLine ( " class:" ) ;
4341 lines . AppendLine ( " hideEmptyMembersBox: true" ) ;
4442 lines . AppendLine ( "---" ) ;
@@ -83,13 +81,13 @@ public Lines Build(CompositionCode composition)
8381
8482 if ( composition . TotalDisposablesCount > 0 )
8583 {
86- classes . Add ( new Class ( nameof ( System ) , "IDisposable" , "abstract " , null , new Lines ( ) ) ) ;
84+ classes . Add ( new Class ( nameof ( System ) , "IDisposable" , "interface " , null , new Lines ( ) ) ) ;
8785 lines . AppendLine ( $ "{ composition . Name . ClassName } --|> IDisposable") ;
8886 }
8987
9088 if ( composition . AsyncDisposableCount > 0 )
9189 {
92- classes . Add ( new Class ( nameof ( System ) , "IAsyncDisposable" , "abstract " , null , new Lines ( ) ) ) ;
90+ classes . Add ( new Class ( nameof ( System ) , "IAsyncDisposable" , "interface " , null , new Lines ( ) ) ) ;
9391 lines . AppendLine ( $ "{ composition . Name . ClassName } --|> IAsyncDisposable") ;
9492 }
9593
@@ -103,16 +101,31 @@ public Lines Build(CompositionCode composition)
103101 }
104102
105103 var contracts = injectionsBuilder . Build ( new ContractsBuildContext ( node . Binding , MdTag . ContextTag , null ) ) ;
106- foreach ( var contract in contracts )
104+ foreach ( var contractGroup in contracts
105+ . Where ( c => ! types . TypeEquals ( node . Type , c . Type ) )
106+ . GroupBy ( c => c . Type , typeSymbolComparer . Dependency ) )
107107 {
108- if ( types . TypeEquals ( node . Type , contract . Type ) )
108+ var contractType = contractGroup . First ( ) . Type ;
109+ typeSymbols . Add ( contractType ) ;
110+
111+ var hasExplicitTag = contractGroup . Any ( c => c . Tag is not null and not MdTagOnSites ) ;
112+ string label ;
113+ if ( ! hasExplicitTag )
109114 {
110- continue ;
115+ label = "" ;
116+ }
117+ else
118+ {
119+ var parts = contractGroup
120+ . Select ( c => c . Tag is null or MdTagOnSites ? "default" : EscapeTag ( c . Tag ) )
121+ . Distinct ( )
122+ . OrderBy ( s => s == "default" ? 1 : 0 )
123+ . ThenBy ( s => s )
124+ . ToList ( ) ;
125+ label = $ " : { string . Join ( ", " , parts ) } ";
111126 }
112127
113- typeSymbols . Add ( contract . Type ) ;
114- var tag = FormatTag ( contract . Tag ) ;
115- lines . AppendLine ( $ "{ FormatType ( setup , node . Type , DefaultFormatOptions ) } --|> { FormatType ( setup , contract . Type , DefaultFormatOptions ) } { ( string . IsNullOrWhiteSpace ( tag ) ? "" : $ " : { tag } ") } ") ;
128+ lines . AppendLine ( $ "{ FormatType ( setup , node . Type , DefaultFormatOptions ) } --|> { FormatType ( setup , contractType , DefaultFormatOptions ) } { label } ") ;
116129 }
117130
118131 var classDiagramWalker = new ClassDiagramWalker ( setup , marker , this , classes , DefaultFormatOptions , locationProvider ) ;
@@ -158,7 +171,11 @@ public Lines Build(CompositionCode composition)
158171 }
159172
160173 var tags = arg . Binding . Contracts . SelectMany ( i => i . Tags . Select ( tag => tag . Value ) ) . ToList ( ) ;
161- lines . AppendLine ( $ "{ targetType } o-- { sourceType } : { ( tags . Count > 0 ? FormatTags ( tags ) + " " : "" ) } Argument \\ \" { arg . Source . ArgName } \\ \" ") ;
174+ var formattedTags = tags . Count > 0 ? FormatTags ( tags ) : "" ;
175+ var argLabel = formattedTags . Length > 0
176+ ? $ "{ formattedTags } Argument \\ \" { arg . Source . ArgName } \\ \" "
177+ : $ "Argument \\ \" { arg . Source . ArgName } \\ \" ";
178+ lines . AppendLine ( $ "{ targetType } o-- { sourceType } : { argLabel } ") ;
162179 }
163180 else
164181 {
@@ -168,7 +185,11 @@ public Lines Build(CompositionCode composition)
168185 }
169186
170187 var relationship = dependency . Source . Lifetime == Lifetime . Transient ? "*--" : "o--" ;
171- lines . AppendLine ( $ "{ targetType } { relationship } { FormatCardinality ( count , dependency . Source . Lifetime ) } { sourceType } : { FormatDependency ( setup , dependency , DefaultFormatOptions ) } ") ;
188+ var cardinality = FormatCardinality ( count , dependency . Source . Lifetime ) ;
189+ var head = cardinality . Length > 0
190+ ? $ "{ targetType } { relationship } { cardinality } { sourceType } "
191+ : $ "{ targetType } { relationship } { sourceType } ";
192+ lines . AppendLine ( $ "{ head } : { FormatDependency ( setup , dependency , DefaultFormatOptions ) } ") ;
172193 }
173194 }
174195 }
@@ -232,53 +253,50 @@ private string FormatRoot(MdSetup setup, Root root)
232253 rootArgsStr = $ "({ string . Join ( ", " , root . RootArgs . Select ( arg => $ "{ ResolveTypeName ( setup , arg . InstanceType ) } { arg . Name } ") ) } )";
233254 }
234255
235- var displayName = root . IsPublic ? root . DisplayName : "_" ;
236- return $ "{ FormatType ( setup , root . Injection . Type , DefaultFormatOptions ) } { displayName } { typeArgsStr } { rootArgsStr } ";
256+ return $ "{ FormatType ( setup , root . Injection . Type , DefaultFormatOptions ) } { root . DisplayName } { typeArgsStr } { rootArgsStr } ";
237257 }
238258
239259 [ SuppressMessage ( "ReSharper" , "InvertIf" ) ]
240260 private static string FormatCardinality ( int count , Lifetime lifetime )
241261 {
242- var cardinality = new StringBuilder ( ) ;
262+ var parts = new List < string > ( 2 ) ;
243263 if ( count > 1 )
244264 {
245- cardinality . Append ( count ) ;
246- cardinality . Append ( ' ' ) ;
265+ parts . Add ( count . ToString ( ) ) ;
247266 }
248267
249268 if ( lifetime != Lifetime . Transient )
250269 {
251- cardinality . Append ( lifetime ) ;
252- if ( count > 1 )
253- {
254- cardinality . Append ( " instances" ) ;
255- }
270+ parts . Add ( lifetime . ToString ( ) ) ;
256271 }
257272
258- if ( cardinality . Length > 0 )
273+ if ( count > 1 )
259274 {
260- cardinality . Insert ( 0 , "\\ \" " ) ;
261- cardinality . Append ( "\\ \" " ) ;
275+ parts . Add ( "instances" ) ;
262276 }
263277
264- return cardinality . ToString ( ) ;
278+ return parts . Count == 0 ? "" : $ " \\ \" { string . Join ( " " , parts ) } \\ \" " ;
265279 }
266280
267- private string FormatDependency ( MdSetup setup , Dependency dependency , FormatOptions options ) =>
268- $ "{ ( dependency . Injection . Tag is null or MdTagOnSites ? "" : FormatTag ( dependency . Injection . Tag ) + " " ) } { FormatSymbol ( setup , dependency . Injection . Type , options ) } ";
281+ private string FormatDependency ( MdSetup setup , Dependency dependency , FormatOptions options )
282+ {
283+ var tag = FormatTag ( dependency . Injection . Tag ) ;
284+ var symbol = FormatSymbol ( setup , dependency . Injection . Type , options ) ;
285+ return tag . Length == 0 ? symbol : $ "{ tag } { symbol } ";
286+ }
269287
270288 private static string FormatTag ( object ? tag ) =>
271289 tag is null or MdTagOnSites
272290 ? ""
273- : EscapeTag ( tag ) + " " ;
291+ : EscapeTag ( tag ) ;
274292
275293 private static string EscapeTag ( object tag ) =>
276294 tag . ValueToString ( "" )
277295 . Replace ( "\" " , "\\ \" " )
278296 . Replace ( ':' , '﹕' ) ;
279297
280298 private static string FormatTags ( IEnumerable < object ? > tags ) =>
281- string . Join ( ", " , tags . Distinct ( ) . Select ( FormatTag ) . OrderBy ( i => i ) ) ;
299+ string . Join ( ", " , tags . Distinct ( ) . Select ( FormatTag ) . Where ( s => s . Length > 0 ) . OrderBy ( i => i ) ) ;
282300
283301 private string FormatSymbol ( MdSetup setup , ISymbol ? symbol , FormatOptions options ) =>
284302 symbol switch
@@ -453,31 +471,31 @@ public string ActualKind
453471 typeKind = "anonymous" ;
454472 }
455473
456- if ( Type . IsRecord )
474+ typeKind = Type . TypeKind switch
457475 {
458- typeKind = "record" ;
459- }
476+ TypeKind . Interface or TypeKind . Enum or TypeKind . Delegate or TypeKind . Struct => Type . TypeKind . ToString ( ) . ToLower ( ) ,
477+ _ => typeKind
478+ } ;
460479
461480 if ( Type is IArrayTypeSymbol )
462481 {
463482 typeKind = "array" ;
464483 }
465484
466- if ( Type . IsTupleType )
485+ if ( Type . IsAbstract && Type . TypeKind == TypeKind . Class )
467486 {
468- typeKind = "tuple " ;
487+ typeKind = "abstract " ;
469488 }
470489
471- if ( Type . IsAbstract )
490+ if ( Type . IsRecord )
472491 {
473- typeKind = "abstract " ;
492+ typeKind = "record " ;
474493 }
475494
476- typeKind = Type . TypeKind switch
495+ if ( Type . IsTupleType )
477496 {
478- TypeKind . Interface or TypeKind . Enum or TypeKind . Delegate or TypeKind . Struct => Type . TypeKind . ToString ( ) . ToLower ( ) ,
479- _ => typeKind
480- } ;
497+ typeKind = "tuple" ;
498+ }
481499
482500 return string . IsNullOrWhiteSpace ( typeKind ) ? Type . TypeKind . ToString ( ) . ToLower ( ) : typeKind ;
483501 }
0 commit comments