@@ -30,37 +30,14 @@ public partial class ReactiveCommandGenerator
3030 private const string Create = ".Create" ;
3131 private const string CreateO = ".CreateFromObservable" ;
3232 private const string CreateT = ".CreateFromTask" ;
33+ private const string ObsoleteReason = "Commands are initialized automatically. Method will be removed in future version." ;
3334
3435 /// <summary>
3536 /// A container for all the logic for <see cref="ReactiveCommandGenerator"/>.
3637 /// </summary>
3738 internal static class Execute
3839 {
39- internal static MethodDeclarationSyntax GetCommandInitiliser ( CommandInfo [ ] commandExtensionInfos )
40- {
41- using var commandInitilisers = ImmutableArrayBuilder < StatementSyntax > . Rent ( ) ;
42-
43- // Add the command initializations
44- foreach ( var commandExtensionInfo in commandExtensionInfos )
45- {
46- var commandName = GetGeneratedCommandName ( commandExtensionInfo . MethodName ) ;
47- var outputType = commandExtensionInfo . GetOutputTypeText ( ) ;
48- var inputType = commandExtensionInfo . GetInputTypeText ( ) ;
49- if ( commandExtensionInfo . ArgumentType == null )
50- {
51- commandInitilisers . Add ( GenerateBasicCommand ( commandExtensionInfo , commandName ) ) ;
52- }
53- else if ( commandExtensionInfo . ArgumentType != null && commandExtensionInfo . IsReturnTypeVoid )
54- {
55- commandInitilisers . Add ( GenerateInCommand ( commandExtensionInfo , commandName , inputType ) ) ;
56- }
57- else if ( commandExtensionInfo . ArgumentType != null && ! commandExtensionInfo . IsReturnTypeVoid )
58- {
59- commandInitilisers . Add ( GenerateInOutCommand ( commandExtensionInfo , commandName , outputType , inputType ) ) ;
60- }
61- }
62-
63- return MethodDeclaration (
40+ internal static MethodDeclarationSyntax GetCommandInitiliser ( ) => MethodDeclaration (
6441 PredefinedType ( Token ( SyntaxKind . VoidKeyword ) ) ,
6542 Identifier ( "InitializeCommands" ) )
6643 . AddAttributeLists (
@@ -69,59 +46,45 @@ internal static MethodDeclarationSyntax GetCommandInitiliser(CommandInfo[] comma
6946 . AddArgumentListArguments (
7047 AttributeArgument ( LiteralExpression ( SyntaxKind . StringLiteralExpression , Literal ( typeof ( ReactiveGenerator ) . FullName ) ) ) ,
7148 AttributeArgument ( LiteralExpression ( SyntaxKind . StringLiteralExpression , Literal ( typeof ( ReactiveGenerator ) . Assembly . GetName ( ) . Version . ToString ( ) ) ) ) ) ) ) ,
72- AttributeList ( SingletonSeparatedList ( Attribute ( IdentifierName ( AttributeDefinitions . ExcludeFromCodeCoverage ) ) ) ) )
49+ AttributeList ( SingletonSeparatedList ( Attribute ( IdentifierName ( AttributeDefinitions . ExcludeFromCodeCoverage ) ) ) ) ,
50+ AttributeList ( SingletonSeparatedList ( Attribute ( IdentifierName ( AttributeDefinitions . Obsolete ) )
51+ . AddArgumentListArguments (
52+ AttributeArgument ( LiteralExpression ( SyntaxKind . StringLiteralExpression , Literal ( ObsoleteReason ) ) ) ) ) ) )
7353 . WithModifiers ( TokenList ( Token ( SyntaxKind . ProtectedKeyword ) ) )
74- . WithBody ( Block ( commandInitilisers . ToImmutable ( ) ) ) ;
54+ . WithBody ( Block ( ) ) ;
7555
76- static StatementSyntax GenerateBasicCommand ( CommandInfo commandExtensionInfo , string commandName )
77- {
78- var commandType = commandExtensionInfo . IsObservable ? CreateO : commandExtensionInfo . IsTask ? CreateT : Create ;
79- if ( string . IsNullOrEmpty ( commandExtensionInfo . CanExecuteObservableName ) )
80- {
81- return ParseStatement ( $ "{ commandName } = { RxCmd } { commandType } ({ commandExtensionInfo . MethodName } );") ;
82- }
56+ internal static MemberDeclarationSyntax [ ] GetCommandProperty ( CommandInfo commandExtensionInfo )
57+ {
58+ var outputType = commandExtensionInfo . GetOutputTypeText ( ) ;
59+ var inputType = commandExtensionInfo . GetInputTypeText ( ) ;
60+ var commandName = GetGeneratedCommandName ( commandExtensionInfo . MethodName ) ;
61+ var fieldName = GetGeneratedFieldName ( commandName ) ;
8362
84- return ParseStatement ( $ "{ commandName } = { RxCmd } { commandType } ({ commandExtensionInfo . MethodName } , { commandExtensionInfo . CanExecuteObservableName } { ( commandExtensionInfo . CanExecuteTypeInfo == CanExecuteTypeInfo . MethodObservable ? "()" : string . Empty ) } );") ;
63+ ExpressionSyntax initializer ;
64+ if ( commandExtensionInfo . ArgumentType == null )
65+ {
66+ initializer = GenerateBasicCommand ( commandExtensionInfo , fieldName ) ;
8567 }
86-
87- static StatementSyntax GenerateInOutCommand ( CommandInfo commandExtensionInfo , string commandName , string outputType , string inputType )
68+ else if ( commandExtensionInfo . ArgumentType != null && commandExtensionInfo . IsReturnTypeVoid )
8869 {
89- var commandType = commandExtensionInfo . IsObservable ? CreateO : commandExtensionInfo . IsTask ? CreateT : Create ;
90- if ( string . IsNullOrEmpty ( commandExtensionInfo . CanExecuteObservableName ) )
91- {
92- return ParseStatement ( $ "{ commandName } = { RxCmd } { commandType } <{ inputType } , { outputType } >({ commandExtensionInfo . MethodName } );") ;
93- }
94-
95- return ParseStatement ( $ "{ commandName } = { RxCmd } { commandType } <{ inputType } , { outputType } >({ commandExtensionInfo . MethodName } , { commandExtensionInfo . CanExecuteObservableName } { ( commandExtensionInfo . CanExecuteTypeInfo == CanExecuteTypeInfo . MethodObservable ? "()" : string . Empty ) } );") ;
70+ initializer = GenerateInCommand ( commandExtensionInfo , fieldName , inputType ) ;
9671 }
97-
98- static StatementSyntax GenerateInCommand ( CommandInfo commandExtensionInfo , string commandName , string inputType )
72+ else if ( commandExtensionInfo . ArgumentType != null && ! commandExtensionInfo . IsReturnTypeVoid )
9973 {
100- var commandType = commandExtensionInfo . IsTask ? CreateT : Create ;
101- if ( string . IsNullOrEmpty ( commandExtensionInfo . CanExecuteObservableName ) )
102- {
103- return ParseStatement ( $ "{ commandName } = { RxCmd } { commandType } <{ inputType } >({ commandExtensionInfo . MethodName } );") ;
104- }
105-
106- return ParseStatement ( $ "{ commandName } = { RxCmd } { commandType } <{ inputType } >({ commandExtensionInfo . MethodName } , { commandExtensionInfo . CanExecuteObservableName } { ( commandExtensionInfo . CanExecuteTypeInfo == CanExecuteTypeInfo . MethodObservable ? "()" : string . Empty ) } );") ;
74+ initializer = GenerateInOutCommand ( commandExtensionInfo , fieldName , outputType , inputType ) ;
75+ }
76+ else
77+ {
78+ return [ ] ;
10779 }
108- }
109-
110- internal static MemberDeclarationSyntax GetCommandProperty ( CommandInfo commandExtensionInfo )
111- {
112- var outputType = commandExtensionInfo . GetOutputTypeText ( ) ;
113- var inputType = commandExtensionInfo . GetInputTypeText ( ) ;
114- var commandName = GetGeneratedCommandName ( commandExtensionInfo . MethodName ) ;
11580
11681 // Prepare any forwarded property attributes
11782 var forwardedPropertyAttributes =
11883 commandExtensionInfo . ForwardedPropertyAttributes
11984 . Select ( static a => AttributeList ( SingletonSeparatedList ( a . GetSyntax ( ) ) ) )
12085 . ToImmutableArray ( ) ;
12186
122- var commandDeclaration = PropertyDeclaration (
123- NullableType (
124- QualifiedName (
87+ var qualifiedName = QualifiedName (
12588 IdentifierName ( ReactiveUI ) ,
12689 GenericName (
12790 Identifier ( ReactiveCommand ) )
@@ -133,18 +96,63 @@ internal static MemberDeclarationSyntax GetCommandProperty(CommandInfo commandEx
13396 IdentifierName ( inputType ) ,
13497 Token ( SyntaxKind . CommaToken ) ,
13598 IdentifierName ( outputType )
136- } ) ) ) ) ) ,
99+ } ) ) ) ) ;
100+
101+ var fieldDeclaration = FieldDeclaration (
102+ VariableDeclaration ( NullableType ( qualifiedName ) ) )
103+ . AddDeclarationVariables ( VariableDeclarator ( fieldName ) )
104+ . AddAttributeLists ( AttributeList ( SingletonSeparatedList (
105+ Attribute ( IdentifierName ( AttributeDefinitions . GeneratedCode ) )
106+ . AddArgumentListArguments (
107+ AttributeArgument ( LiteralExpression ( SyntaxKind . StringLiteralExpression , Literal ( typeof ( ReactiveCommandGenerator ) . FullName ) ) ) ,
108+ AttributeArgument ( LiteralExpression ( SyntaxKind . StringLiteralExpression , Literal ( typeof ( ReactiveCommandGenerator ) . Assembly . GetName ( ) . Version . ToString ( ) ) ) ) ) ) ) )
109+ . AddModifiers (
110+ Token ( SyntaxKind . PrivateKeyword ) )
111+ . NormalizeWhitespace ( ) ;
112+
113+ var commandDeclaration = PropertyDeclaration (
114+ qualifiedName ,
137115 Identifier ( commandName ) )
138116 . AddModifiers ( Token ( SyntaxKind . PublicKeyword ) )
139117 . AddAccessorListAccessors (
140118 AccessorDeclaration ( SyntaxKind . GetAccessorDeclaration )
141- . WithSemicolonToken ( Token ( SyntaxKind . SemicolonToken ) ) ,
142- AccessorDeclaration ( SyntaxKind . SetAccessorDeclaration )
143- . WithModifiers ( TokenList ( Token ( SyntaxKind . PrivateKeyword ) ) )
144- . WithSemicolonToken ( Token ( SyntaxKind . SemicolonToken ) ) )
119+ . WithExpressionBody ( ArrowExpressionClause ( initializer ) ) )
145120 . AddAttributeLists ( [ .. forwardedPropertyAttributes ] )
146121 . NormalizeWhitespace ( ) ;
147- return commandDeclaration ;
122+ return [ fieldDeclaration , commandDeclaration ] ;
123+
124+ static ExpressionSyntax GenerateBasicCommand ( CommandInfo commandExtensionInfo , string fieldName )
125+ {
126+ var commandType = commandExtensionInfo . IsObservable ? CreateO : commandExtensionInfo . IsTask ? CreateT : Create ;
127+ if ( string . IsNullOrEmpty ( commandExtensionInfo . CanExecuteObservableName ) )
128+ {
129+ return ParseExpression ( $ "{ fieldName } ??= { RxCmd } { commandType } ({ commandExtensionInfo . MethodName } );") ;
130+ }
131+
132+ return ParseExpression ( $ "{ fieldName } ??= { RxCmd } { commandType } ({ commandExtensionInfo . MethodName } , { commandExtensionInfo . CanExecuteObservableName } { ( commandExtensionInfo . CanExecuteTypeInfo == CanExecuteTypeInfo . MethodObservable ? "()" : string . Empty ) } );") ;
133+ }
134+
135+ static ExpressionSyntax GenerateInOutCommand ( CommandInfo commandExtensionInfo , string fieldName , string outputType , string inputType )
136+ {
137+ var commandType = commandExtensionInfo . IsObservable ? CreateO : commandExtensionInfo . IsTask ? CreateT : Create ;
138+ if ( string . IsNullOrEmpty ( commandExtensionInfo . CanExecuteObservableName ) )
139+ {
140+ return ParseExpression ( $ "{ fieldName } ??= { RxCmd } { commandType } <{ inputType } , { outputType } >({ commandExtensionInfo . MethodName } );") ;
141+ }
142+
143+ return ParseExpression ( $ "{ fieldName } ??= { RxCmd } { commandType } <{ inputType } , { outputType } >({ commandExtensionInfo . MethodName } , { commandExtensionInfo . CanExecuteObservableName } { ( commandExtensionInfo . CanExecuteTypeInfo == CanExecuteTypeInfo . MethodObservable ? "()" : string . Empty ) } );") ;
144+ }
145+
146+ static ExpressionSyntax GenerateInCommand ( CommandInfo commandExtensionInfo , string fieldName , string inputType )
147+ {
148+ var commandType = commandExtensionInfo . IsTask ? CreateT : Create ;
149+ if ( string . IsNullOrEmpty ( commandExtensionInfo . CanExecuteObservableName ) )
150+ {
151+ return ParseExpression ( $ "{ fieldName } ??= { RxCmd } { commandType } <{ inputType } >({ commandExtensionInfo . MethodName } );") ;
152+ }
153+
154+ return ParseExpression ( $ "{ fieldName } ??= { RxCmd } { commandType } <{ inputType } >({ commandExtensionInfo . MethodName } , { commandExtensionInfo . CanExecuteObservableName } { ( commandExtensionInfo . CanExecuteTypeInfo == CanExecuteTypeInfo . MethodObservable ? "()" : string . Empty ) } );") ;
155+ }
148156 }
149157
150158 internal static bool IsTaskReturnType ( ITypeSymbol ? typeSymbol )
@@ -458,5 +466,8 @@ internal static string GetGeneratedCommandName(string methodName)
458466
459467 return $ "{ char . ToUpper ( commandName [ 0 ] , CultureInfo . InvariantCulture ) } { commandName . Substring ( 1 ) } Command";
460468 }
469+
470+ internal static string GetGeneratedFieldName ( string generatedCommandName ) =>
471+ $ "_{ char . ToLower ( generatedCommandName [ 0 ] , CultureInfo . InvariantCulture ) } { generatedCommandName . Substring ( 1 ) } ";
461472 }
462473}
0 commit comments