11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4+ using System . Text ;
45using Microsoft . CodeAnalysis ;
56using Microsoft . CodeAnalysis . CSharp ;
67using Microsoft . CodeAnalysis . CSharp . Syntax ;
@@ -64,13 +65,19 @@ public CliCommandInfo(ISymbol symbol, SyntaxNode syntaxNode, AttributeData attri
6465
6566 var visitedProperties = new Dictionary < string , ISymbol > ( StringComparer . Ordinal ) ;
6667 var addedProperties = new HashSet < string > ( StringComparer . Ordinal ) ;
68+ Dictionary < ITypeSymbol , ( int Index , CliCommandSettings Settings ) > ancestorsByType = Settings
69+ . GetParentTree ( )
70+ . Select ( ( s , i ) => ( i , Setings : s ) )
71+ . ToDictionary ( x => x . Setings . Symbol , ( IEqualityComparer < ITypeSymbol > ) SymbolEqualityComparer . Default ) ;
72+
6773 foreach ( var member in Symbol . GetAllMembers ( ) )
6874 {
69- if ( member is IPropertySymbol )
75+ if ( member is IPropertySymbol property )
7076 {
7177 if ( addedProperties . Contains ( member . Name ) )
7278 continue ;
7379
80+ bool added = false ;
7481 foreach ( var memberAttributeData in member . GetAttributes ( ) )
7582 {
7683 var attributeFullName = memberAttributeData . AttributeClass ? . ToCompareString ( ) ;
@@ -81,12 +88,19 @@ public CliCommandInfo(ISymbol symbol, SyntaxNode syntaxNode, AttributeData attri
8188 {
8289 childOptions . Add ( new CliOptionInfo ( visitedMember ?? member , null , memberAttributeData , SemanticModel , this ) ) ;
8390 addedProperties . Add ( member . Name ) ;
91+ added = true ;
8492 } else if ( attributeFullName == CliArgumentInfo . AttributeFullName )
8593 {
8694 childArguments . Add ( new CliArgumentInfo ( visitedMember ?? member , null , memberAttributeData , SemanticModel , this ) ) ;
8795 addedProperties . Add ( member . Name ) ;
96+ added = true ;
8897 }
8998 }
99+ if ( ! added && ancestorsByType . TryGetValue ( property . Type , out var ancestorInfo ) )
100+ {
101+ childParentCommandRefs . Add ( new CliParentCommandRefInfo ( property , null , SemanticModel , ancestorInfo . Index , ancestorInfo . Settings ) ) ;
102+ addedProperties . Add ( member . Name ) ;
103+ }
90104
91105 if ( ! visitedProperties . ContainsKey ( member . Name ) )
92106 visitedProperties . Add ( member . Name , member ) ;
@@ -164,6 +178,9 @@ public static CliCommandInfo From(GeneratorAttributeSyntaxContext attributeSynta
164178 public IReadOnlyList < CliCommandInfo > ChildCommands => childCommands ;
165179 private readonly List < CliCommandInfo > childCommands = new List < CliCommandInfo > ( ) ;
166180
181+ public IReadOnlyList < CliParentCommandRefInfo > ChildParentCommandRefs => childParentCommandRefs ;
182+ private readonly List < CliParentCommandRefInfo > childParentCommandRefs = new List < CliParentCommandRefInfo > ( ) ;
183+
167184 private void Analyze ( )
168185 {
169186 if ( ( Symbol . DeclaredAccessibility != Accessibility . Public && Symbol . DeclaredAccessibility != Accessibility . Internal )
@@ -206,16 +223,21 @@ public override void ReportDiagnostics(SourceProductionContext sourceProductionC
206223
207224 foreach ( var child in ChildCommands )
208225 child . ReportDiagnostics ( sourceProductionContext ) ;
226+
227+ foreach ( var child in ChildParentCommandRefs )
228+ child . ReportDiagnostics ( sourceProductionContext ) ;
209229 }
210230
211231 public void AppendCSharpDefineString ( CodeStringBuilder sb , bool addNamespaceBlock )
212232 {
213233 var childOptionsWithoutProblem = ChildOptions . Where ( c => ! c . HasProblem ) . ToArray ( ) ;
214234 var childArgumentsWithoutProblem = ChildArguments . Where ( c => ! c . HasProblem ) . ToArray ( ) ;
215235 var childCommandsWithoutProblem = ChildCommands . Where ( c => ! c . HasProblem ) . ToArray ( ) ;
236+ var childParentCommandRefsWithoutProblem = ChildParentCommandRefs . Where ( c => ! c . HasProblem ) . ToArray ( ) ;
216237 var handlerWithoutProblem = ( Handler != null && ! Handler . HasProblem ) ? Handler : null ;
217238 var memberHasRequiredModifier = childOptionsWithoutProblem . Any ( o => o . Symbol . IsRequired )
218- || childArgumentsWithoutProblem . Any ( a => a . Symbol . IsRequired ) ;
239+ || childArgumentsWithoutProblem . Any ( a => a . Symbol . IsRequired )
240+ || childParentCommandRefsWithoutProblem . Any ( r => r . Symbol . IsRequired ) ;
219241
220242 if ( string . IsNullOrEmpty ( GeneratedClassNamespace ) )
221243 addNamespaceBlock = false ;
@@ -308,7 +330,7 @@ public void AppendCSharpDefineString(CodeStringBuilder sb, bool addNamespaceBloc
308330 }
309331
310332 sb . AppendLine ( ) ;
311- using ( sb . AppendBlockStart ( $ "BindFunc = (parseResult ) =>", ";" ) )
333+ using ( sb . AppendBlockStart ( $ "BindFunc = (cliBindContext ) =>", ";" ) )
312334 {
313335 var varTargetClass = "targetClass" ;
314336
@@ -320,7 +342,7 @@ public void AppendCSharpDefineString(CodeStringBuilder sb, bool addNamespaceBloc
320342 {
321343 var cliOptionInfo = childOptionsWithoutProblem [ index ] ;
322344 var varOption = $ "option{ index } ";
323- sb . AppendLine ( $ "{ varTargetClass } .{ cliOptionInfo . Symbol . Name } = GetValueForOption(parseResult , { varOption } );") ;
345+ sb . AppendLine ( $ "{ varTargetClass } .{ cliOptionInfo . Symbol . Name } = GetValueForOption(cliBindContext.ParseResult , { varOption } );") ;
324346 }
325347
326348 sb . AppendLine ( ) ;
@@ -329,7 +351,15 @@ public void AppendCSharpDefineString(CodeStringBuilder sb, bool addNamespaceBloc
329351 {
330352 var cliArgumentInfo = childArgumentsWithoutProblem [ index ] ;
331353 var varArgument = $ "argument{ index } ";
332- sb . AppendLine ( $ "{ varTargetClass } .{ cliArgumentInfo . Symbol . Name } = GetValueForArgument(parseResult, { varArgument } );") ;
354+ sb . AppendLine ( $ "{ varTargetClass } .{ cliArgumentInfo . Symbol . Name } = GetValueForArgument(cliBindContext.ParseResult, { varArgument } );") ;
355+ }
356+
357+ sb . AppendLine ( ) ;
358+ sb . AppendLine ( "// Set the values for the parent command references" ) ;
359+ for ( var index = 0 ; index < childParentCommandRefsWithoutProblem . Length ; index ++ )
360+ {
361+ var cliParentCommandRefInfo = childParentCommandRefsWithoutProblem [ index ] ;
362+ sb . AppendLine ( $ "{ varTargetClass } .{ cliParentCommandRefInfo . Symbol . Name } = cliBindContext.BindOrGetBindResult<{ cliParentCommandRefInfo . Symbol . Type . ToReferenceString ( ) } >();") ;
333363 }
334364
335365 sb . AppendLine ( ) ;
@@ -339,6 +369,7 @@ public void AppendCSharpDefineString(CodeStringBuilder sb, bool addNamespaceBloc
339369 sb . AppendLine ( ) ;
340370 var varParseResult = "parseResult" ;
341371 var varCancellationToken = "cancellationToken" ;
372+ var varCliBindContext = "cliBindContext" ;
342373 var varCliContext = "cliContext" ;
343374 var isAsync = ( handlerWithoutProblem != null && handlerWithoutProblem . IsAsync ) ;
344375 using ( sb . AppendBlockStart ( isAsync
@@ -348,7 +379,8 @@ public void AppendCSharpDefineString(CodeStringBuilder sb, bool addNamespaceBloc
348379 {
349380 var varTargetClass = "targetClass" ;
350381
351- sb . AppendLine ( $ "var { varTargetClass } = ({ definitionClass } ) BindFunc({ varParseResult } );") ;
382+ sb . AppendLine ( $ "var { varCliBindContext } = new DotMake.CommandLine.CliBindContext({ varParseResult } );") ;
383+ sb . AppendLine ( $ "var { varTargetClass } = ({ definitionClass } ) BindFunc({ varCliBindContext } );") ;
352384 sb . AppendLine ( ) ;
353385
354386 sb . AppendLine ( "// Call the command handler" ) ;
0 commit comments