@@ -39,22 +39,15 @@ async Task<VerifyResult> VerifyInner(object? root, Func<Task>? cleanup, IEnumera
3939
4040 List < Target > list = [ ..targets , ..VerifierSettings . GetFileAppenders ( settings ) ] ;
4141
42- // Process root via TryGetRootTarget when root is NOT already in the targets list
43- // This handles:
44- // - VerifyStream with converter: root (info) is separate from targets → process both
45- // - Verify(object, IEnumerable<Target>): root is separate from targets → process both
46- // - Verify(): root is null, targets is empty → TryGetRootTarget handles null appropriately
47- // Skip when:
48- // - Verify(object): root is in targets list → avoid duplicate processing
42+ // Check if root is in targets list (to avoid duplicate processing)
4943 var rootInTargets = root != null && list . Any ( t => ReferenceEquals ( t . Data , root ) ) ;
50- if ( ! rootInTargets && TryGetRootTarget ( root , ignoreNullRoot , out var rootTarget ) )
51- {
52- resultTargets . Add ( rootTarget . Value ) ;
53- }
5444
45+ // Process extension conversions first (may produce converter info that becomes root)
46+ List < object > ? converterInfos = null ;
5547 if ( doExtensionConversion )
5648 {
5749 var result = new List < Target > ( ) ;
50+ converterInfos = [ ] ;
5851 foreach ( var target in list )
5952 {
6053 if ( ! target . PerformConversion ||
@@ -69,21 +62,43 @@ target.Extension is null ||
6962 cleanup += itemCleanup ;
7063 if ( info != null )
7164 {
72- result . Add (
73- new (
74- settings . TxtOrJson ,
75- JsonFormatter . AsJson (
76- settings ,
77- counter ,
78- info ) ) ) ;
65+ converterInfos . Add ( info ) ;
7966 }
8067
8168 result . AddRange ( converted ) ;
8269 }
8370
71+ // If root is null and converters returned info, use converter info as root (for appenders)
72+ if ( ! rootInTargets && root == null && converterInfos . Count > 0 )
73+ {
74+ root = converterInfos . Count == 1 ? converterInfos [ 0 ] : converterInfos ;
75+ converterInfos = null ; // Already used as root, don't add again
76+ }
77+
8478 list = result ;
8579 }
8680
81+ // Process root via TryGetRootTarget (after extension conversion so converter info can become root)
82+ if ( ! rootInTargets && TryGetRootTarget ( root , ignoreNullRoot , out var rootTarget ) )
83+ {
84+ resultTargets . Add ( rootTarget . Value ) ;
85+ }
86+
87+ // Add converter infos right after root (before other targets)
88+ if ( converterInfos != null )
89+ {
90+ foreach ( var info in converterInfos )
91+ {
92+ resultTargets . Add (
93+ new (
94+ settings . TxtOrJson ,
95+ JsonFormatter . AsJson (
96+ settings ,
97+ counter ,
98+ info ) ) ) ;
99+ }
100+ }
101+
87102 // Resolve all targets (including objects) to ResolvedTargets
88103 var extraTargets = new List < ResolvedTarget > ( ) ;
89104 var noScrubTargets = new List < ResolvedTarget > ( ) ;
@@ -260,6 +275,15 @@ target.Extension is null ||
260275 JsonFormatter . AsJson ( settings , counter , conversionResult . Info ) ) ) ;
261276 }
262277
278+ // Add appends as first target if present (typed converters don't include appends in their output)
279+ var converterAppends = VerifierSettings . GetJsonAppenders ( settings ) ;
280+ if ( converterAppends . Count > 0 )
281+ {
282+ results . Insert ( 0 , new (
283+ settings . TxtOrJson ,
284+ JsonFormatter . AsJson ( settings , counter , new InfoBuilder ( true , null , converterAppends ) ) ) ) ;
285+ }
286+
263287 return ( results , cleanup , true ) ;
264288 }
265289
0 commit comments