Skip to content

Commit 0564bae

Browse files
authored
Feature: Add CanExecute to ReactiveCommand (#8)
* Feature Add CanExecute to ReactiveCommand * Update to correct generator
1 parent 700cbb6 commit 0564bae

File tree

8 files changed

+426
-36
lines changed

8 files changed

+426
-36
lines changed

src/ReactiveUI.SourceGenerators.Execute/Program.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,18 @@ public TestClass()
8585
Console.ReadLine();
8686
}
8787

88+
/// <summary>
89+
/// Gets the can execute test1.
90+
/// </summary>
91+
/// <value>
92+
/// The can execute test1.
93+
/// </value>
94+
public IObservable<bool> CanExecuteTest1 => Observable.Return(true);
95+
8896
/// <summary>
8997
/// Test1s this instance.
9098
/// </summary>
91-
[ReactiveCommand]
99+
[ReactiveCommand(CanExecute = nameof(CanExecuteTest1))]
92100
private void Test1() => Console.Out.WriteLine("Test1");
93101

94102
/// <summary>

src/ReactiveUI.SourceGenerators/Attributes/ReactiveCommandAttribute.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,13 @@ namespace ReactiveUI.SourceGenerators;
1212
/// </summary>
1313
/// <seealso cref="Attribute" />
1414
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
15-
public sealed class ReactiveCommandAttribute : Attribute;
15+
public sealed class ReactiveCommandAttribute : Attribute
16+
{
17+
/// <summary>
18+
/// Gets the can execute method or property.
19+
/// </summary>
20+
/// <value>
21+
/// The name of the CanExecute Observable of bool.
22+
/// </value>
23+
public string? CanExecute { get; init; }
24+
}

src/ReactiveUI.SourceGenerators/Diagnostics/Analyzers/AsyncVoidReturningReactiveCommandMethodAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
namespace ReactiveUI.SourceGenerators;
1515

1616
/// <summary>
17-
/// A diagnostic analyzer that generates a warning when using <c>[RelayCommand]</c> over an <see langword="async"/> <see cref="void"/> method.
17+
/// A diagnostic analyzer that generates a warning when using <c>[ReactiveCommand]</c> over an <see langword="async"/> <see cref="void"/> method.
1818
/// </summary>
1919
[DiagnosticAnalyzer(LanguageNames.CSharp)]
2020
public sealed class AsyncVoidReturningReactiveCommandMethodAnalyzer : DiagnosticAnalyzer

src/ReactiveUI.SourceGenerators/Reactive/ReactiveGenerator.Execute.cs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,27 @@ internal static bool GetFieldInfoFromClass(
303303
return true;
304304
}
305305

306+
/// <summary>
307+
/// Get the generated property name for an input field.
308+
/// </summary>
309+
/// <param name="fieldSymbol">The input <see cref="IFieldSymbol"/> instance to process.</param>
310+
/// <returns>The generated property name for <paramref name="fieldSymbol"/>.</returns>
311+
internal static string GetGeneratedPropertyName(IFieldSymbol fieldSymbol)
312+
{
313+
var propertyName = fieldSymbol.Name;
314+
315+
if (propertyName.StartsWith("m_"))
316+
{
317+
propertyName = propertyName.Substring(2);
318+
}
319+
else if (propertyName.StartsWith("_"))
320+
{
321+
propertyName = propertyName.TrimStart('_');
322+
}
323+
324+
return $"{char.ToUpper(propertyName[0], CultureInfo.InvariantCulture)}{propertyName.Substring(1)}";
325+
}
326+
306327
/// <summary>
307328
/// Validates the containing type for a given field being annotated.
308329
/// </summary>
@@ -357,26 +378,5 @@ private static void GetNullabilityInfo(
357378
fieldSymbol.Type.NullableAnnotation != NullableAnnotation.Annotated &&
358379
semanticModel.Compilation.HasAccessibleTypeWithMetadataName("System.Diagnostics.CodeAnalysis.MemberNotNullAttribute");
359380
}
360-
361-
/// <summary>
362-
/// Get the generated property name for an input field.
363-
/// </summary>
364-
/// <param name="fieldSymbol">The input <see cref="IFieldSymbol"/> instance to process.</param>
365-
/// <returns>The generated property name for <paramref name="fieldSymbol"/>.</returns>
366-
private static string GetGeneratedPropertyName(IFieldSymbol fieldSymbol)
367-
{
368-
var propertyName = fieldSymbol.Name;
369-
370-
if (propertyName.StartsWith("m_"))
371-
{
372-
propertyName = propertyName.Substring(2);
373-
}
374-
else if (propertyName.StartsWith("_"))
375-
{
376-
propertyName = propertyName.TrimStart('_');
377-
}
378-
379-
return $"{char.ToUpper(propertyName[0], CultureInfo.InvariantCulture)}{propertyName.Substring(1)}";
380-
}
381381
}
382382
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
namespace ReactiveUI.SourceGenerators.Input.Models;
7+
8+
internal enum CanExecuteTypeInfo
9+
{
10+
PropertyObservable,
11+
MethodObservable
12+
}

src/ReactiveUI.SourceGenerators/ReactiveCommand/Models/CommandExtensionInfo.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// See the LICENSE file in the project root for full license information.
55

66
using Microsoft.CodeAnalysis;
7+
using ReactiveUI.SourceGenerators.Helpers;
8+
using ReactiveUI.SourceGenerators.Models;
79

810
namespace ReactiveUI.SourceGenerators.Input.Models;
911

@@ -13,7 +15,11 @@ internal record CommandExtensionInfo(
1315
ITypeSymbol? ArgumentType,
1416
bool IsTask,
1517
bool IsReturnTypeVoid,
16-
bool IsObservable)
18+
bool IsObservable,
19+
string? CanExecuteObservableName,
20+
CanExecuteTypeInfo? CanExecuteTypeInfo,
21+
EquatableArray<AttributeInfo> ForwardedFieldAttributes,
22+
EquatableArray<AttributeInfo> ForwardedPropertyAttributes)
1723
{
1824
private const string UnitTypeName = "global::System.Reactive.Unit";
1925

0 commit comments

Comments
 (0)