From 1f485bd9677a028c09be70b2a56bcf599f3d7fe3 Mon Sep 17 00:00:00 2001 From: Thomas Claudius Huber Date: Sun, 10 Dec 2023 16:29:48 +0100 Subject: [PATCH] Add ModelPropertiesToIgnore prop to ViewModel attribute --- .../Model/ViewModelToGenerateTests.cs | 26 +++++++++ .../ViewModelAttributeTests.ModelInput.cs | 54 +++++++++++++++++++ .../Inspectors/ModelMemberInspector.cs | 13 ++++- .../Inspectors/ViewModelAttributeInspector.cs | 15 ++++++ .../Model/ViewModelToGenerate.cs | 3 ++ .../ViewModelGenerator.cs | 7 ++- src/MvvmGen/Attributes/ViewModelAttribute.cs | 6 +++ 7 files changed, 122 insertions(+), 2 deletions(-) diff --git a/src/MvvmGen.SourceGenerators.Tests/Model/ViewModelToGenerateTests.cs b/src/MvvmGen.SourceGenerators.Tests/Model/ViewModelToGenerateTests.cs index 15edcc5..9141bd3 100644 --- a/src/MvvmGen.SourceGenerators.Tests/Model/ViewModelToGenerateTests.cs +++ b/src/MvvmGen.SourceGenerators.Tests/Model/ViewModelToGenerateTests.cs @@ -391,6 +391,31 @@ public void ShouldBeEqual9() Assert.Equal(_viewModelToGenerate1, _viewModelToGenerate2); } + [Fact] + public void ShouldNotBeEqualDifferentModelPropertiesToIgnore1() + { + _viewModelToGenerate2.WrappedModelPropertiesToIgnore = null; + + Assert.NotEqual(_viewModelToGenerate1, _viewModelToGenerate2); + } + + [Fact] + public void ShouldNotBeEqualDifferentModelPropertiesToIgnore2() + { + _viewModelToGenerate2.WrappedModelPropertiesToIgnore = "FirstName"; + + Assert.NotEqual(_viewModelToGenerate1, _viewModelToGenerate2); + } + + [Fact] + public void ShouldBeEqual10() + { + _viewModelToGenerate1.WrappedModelPropertiesToIgnore = null; + _viewModelToGenerate2.WrappedModelPropertiesToIgnore = null; + + Assert.Equal(_viewModelToGenerate1, _viewModelToGenerate2); + } + private static void FillAllProperties(ViewModelToGenerate viewModelToGenerate) { viewModelToGenerate.ClassAccessModifier = "public"; @@ -399,6 +424,7 @@ private static void FillAllProperties(ViewModelToGenerate viewModelToGenerate) viewModelToGenerate.IsEventSubscriber = true; viewModelToGenerate.WrappedModelType = "Employee"; viewModelToGenerate.WrappedModelPropertyName = "EmployeeModel"; + viewModelToGenerate.WrappedModelPropertiesToIgnore = "Address"; viewModelToGenerate.PropertiesToGenerate = new List { diff --git a/src/MvvmGen.SourceGenerators.Tests/ViewModelGeneratorTests/ViewModelAttributeTests.ModelInput.cs b/src/MvvmGen.SourceGenerators.Tests/ViewModelGeneratorTests/ViewModelAttributeTests.ModelInput.cs index 3be03f0..500d3ae 100644 --- a/src/MvvmGen.SourceGenerators.Tests/ViewModelGeneratorTests/ViewModelAttributeTests.ModelInput.cs +++ b/src/MvvmGen.SourceGenerators.Tests/ViewModelGeneratorTests/ViewModelAttributeTests.ModelInput.cs @@ -262,6 +262,60 @@ public bool IsDeveloper protected MyCode.Employee { expectedModelPropertyName } {{ get; set; }} }} }} +"); + } + + [InlineData("ModelType=typeof(Employee)")] + [InlineData("typeof(Employee)")] + [Theory] + public void IgnoreModelProperties(string attributeArgument) + { + ShouldGenerateExpectedCode( + $@"using MvvmGen; + +namespace MyCode +{{ + public class Employee + {{ + public string FirstName {{ get; set; }} + public string LastName {{ get; set; }} + public bool IsDeveloper {{ get; set; }} + }} + + [ViewModel({attributeArgument},ModelPropertiesToIgnore=""LastName, IsDeveloper"")] + public partial class EmployeeViewModel + {{ + }} +}}", + $@"{AutoGeneratedTopContent} + +namespace MyCode +{{ + partial class EmployeeViewModel : global::MvvmGen.ViewModels.ViewModelBase + {{ + public EmployeeViewModel() + {{ + this.OnInitialize(); + }} + + partial void OnInitialize(); + + public string FirstName + {{ + get => Model.FirstName; + set + {{ + if (Model.FirstName != value) + {{ + Model.FirstName = value; + OnPropertyChanged(""FirstName""); + }} + }} + }} + + protected MyCode.Employee Model {{ get; set; }} + }} +}} "); } diff --git a/src/MvvmGen.SourceGenerators/Inspectors/ModelMemberInspector.cs b/src/MvvmGen.SourceGenerators/Inspectors/ModelMemberInspector.cs index 18e9d08..9bb4f15 100644 --- a/src/MvvmGen.SourceGenerators/Inspectors/ModelMemberInspector.cs +++ b/src/MvvmGen.SourceGenerators/Inspectors/ModelMemberInspector.cs @@ -13,9 +13,14 @@ namespace MvvmGen.Inspectors { internal static class ModelMemberInspector { - internal static string? Inspect(AttributeData viewModelAttributeData, IList propertiesToGenerate, string? wrappedModelPropertyName) + internal static string? Inspect(AttributeData viewModelAttributeData, + IList propertiesToGenerate, + string? wrappedModelPropertyName, + string? wrappedModelPropertiesToIgnore) { string? wrappedModelType = null; + var wrappedModelPropsToIgnore = wrappedModelPropertiesToIgnore? + .Split(',').Select(x => x.Trim()).ToList(); var modelTypedConstant = (TypedConstant?)viewModelAttributeData.ConstructorArguments.FirstOrDefault(); @@ -41,6 +46,12 @@ internal static class ModelMemberInspector var propertySymbol = (IPropertySymbol?)methodSymbol.AssociatedSymbol; if (propertySymbol is not null) { + if (wrappedModelPropsToIgnore is not null + && wrappedModelPropsToIgnore.Contains(propertySymbol.Name)) + { + continue; + } + propertiesToGenerate.Add(new PropertyToGenerate( propertySymbol.Name, propertySymbol.Type.ToString(), $"{wrappedModelPropertyName}.{propertySymbol.Name}", propertySymbol.IsReadOnly)); } diff --git a/src/MvvmGen.SourceGenerators/Inspectors/ViewModelAttributeInspector.cs b/src/MvvmGen.SourceGenerators/Inspectors/ViewModelAttributeInspector.cs index a006a03..3794644 100644 --- a/src/MvvmGen.SourceGenerators/Inspectors/ViewModelAttributeInspector.cs +++ b/src/MvvmGen.SourceGenerators/Inspectors/ViewModelAttributeInspector.cs @@ -40,6 +40,21 @@ internal static bool InspectGenerateConstructor(AttributeData viewModelAttribute return modelPropertyName; } + internal static string? InspectModelPropertiesToIgnore(AttributeData viewModelAttributeData) + { + string? propertiesToIgnore = null; + + foreach (var arg in viewModelAttributeData.NamedArguments) + { + if (arg.Key == "ModelPropertiesToIgnore") + { + propertiesToIgnore = arg.Value.Value?.ToString(); + } + } + + return propertiesToIgnore; + } + internal static string InspectCommandType(AttributeData viewModelAttributeData) { string commandType = "DelegateCommand"; diff --git a/src/MvvmGen.SourceGenerators/Model/ViewModelToGenerate.cs b/src/MvvmGen.SourceGenerators/Model/ViewModelToGenerate.cs index 1a35f5a..f57ca2d 100644 --- a/src/MvvmGen.SourceGenerators/Model/ViewModelToGenerate.cs +++ b/src/MvvmGen.SourceGenerators/Model/ViewModelToGenerate.cs @@ -31,6 +31,8 @@ public ViewModelToGenerate(string className, string namespaceName) public string? WrappedModelPropertyName { get; set; } + public string? WrappedModelPropertiesToIgnore { get; set; } + public bool IsEventSubscriber { get; set; } public bool GenerateConstructor { get; set; } @@ -66,6 +68,7 @@ public bool Equals(ViewModelToGenerate? other) NamespaceName == other.NamespaceName && WrappedModelType == other.WrappedModelType && WrappedModelPropertyName == other.WrappedModelPropertyName && + WrappedModelPropertiesToIgnore == other.WrappedModelPropertiesToIgnore && IsEventSubscriber == other.IsEventSubscriber && GenerateConstructor == other.GenerateConstructor && CommandType== other.CommandType && diff --git a/src/MvvmGen.SourceGenerators/ViewModelGenerator.cs b/src/MvvmGen.SourceGenerators/ViewModelGenerator.cs index 5ed104c..357719a 100644 --- a/src/MvvmGen.SourceGenerators/ViewModelGenerator.cs +++ b/src/MvvmGen.SourceGenerators/ViewModelGenerator.cs @@ -92,7 +92,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context) }; viewModelToGenerate.WrappedModelPropertyName = ViewModelAttributeInspector.InspectModelPropertyName(viewModelAttributeData); - viewModelToGenerate.WrappedModelType = ModelMemberInspector.Inspect(viewModelAttributeData, viewModelToGenerate.PropertiesToGenerate, viewModelToGenerate.WrappedModelPropertyName); + viewModelToGenerate.WrappedModelPropertiesToIgnore = ViewModelAttributeInspector.InspectModelPropertiesToIgnore(viewModelAttributeData); + viewModelToGenerate.WrappedModelType = + ModelMemberInspector.Inspect(viewModelAttributeData, + viewModelToGenerate.PropertiesToGenerate, + viewModelToGenerate.WrappedModelPropertyName, + viewModelToGenerate.WrappedModelPropertiesToIgnore); viewModelToGenerate.ViewModelInterfaceToGenerate = ViewModelGenerateInterfaceAttributeInspector.Inspect(viewModelClassSymbol, viewModelToGenerate.PropertiesToGenerate, viewModelToGenerate.CommandsToGenerate, context.Node.SyntaxTree); diff --git a/src/MvvmGen/Attributes/ViewModelAttribute.cs b/src/MvvmGen/Attributes/ViewModelAttribute.cs index 171a1c7..7d139f6 100644 --- a/src/MvvmGen/Attributes/ViewModelAttribute.cs +++ b/src/MvvmGen/Attributes/ViewModelAttribute.cs @@ -40,6 +40,12 @@ public ViewModelAttribute(Type modelType) /// public string? ModelPropertyName { get; set; } + /// + /// Gets or sets a comma separated list of model properties that should not be generated + /// in the ViewModel for the model that you specified with the property. + /// + public string? ModelPropertiesToIgnore { get; set; } + /// /// Gets or sets if a constructor is generated. Default value is true. ///