Skip to content

Commit c294d7d

Browse files
committed
Handle lazy fields too
And adds tests.
1 parent f7b9183 commit c294d7d

2 files changed

Lines changed: 66 additions & 11 deletions

File tree

src/ImmutableObjectGraph.Generation.Tests/TestSources/FileSystem.Tests.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,45 @@ public void RootedStruct_EqualityOperators()
572572
Assert.True(r1a != r1Rerooted);
573573
}
574574

575+
[Fact]
576+
public void Builder_INotifyPropertyChanged_SimpleValue()
577+
{
578+
var builder = FileSystemFile.CreateBuilder();
579+
var raisedName = new Stack<string>();
580+
builder.PropertyChanged += (s, e) => raisedName.Push(e.PropertyName);
581+
582+
// Set a value property and assert it raises the changed event once.
583+
builder.PathSegment = "fo";
584+
Assert.Equal(nameof(builder.PathSegment), raisedName.Pop());
585+
Assert.Equal(0, raisedName.Count);
586+
587+
// Set it to the same value and assert no event is raised.
588+
builder.PathSegment = builder.PathSegment;
589+
Assert.Equal(0, raisedName.Count);
590+
}
591+
592+
[Fact]
593+
public void Builder_INotifyPropertyChanged_LazyImmutable()
594+
{
595+
var builder = FileSystemFile.CreateBuilder();
596+
var raisedName = new Stack<string>();
597+
builder.PropertyChanged += (s, e) => raisedName.Push(e.PropertyName);
598+
599+
// Set a Builder property and assert it raises the changed event once.
600+
builder.Data = RichData.CreateBuilder();
601+
Assert.Equal(nameof(builder.Data), raisedName.Pop());
602+
Assert.Equal(0, raisedName.Count);
603+
604+
// Set it to the same value and assert no event is raised.
605+
builder.Data = builder.Data;
606+
Assert.Equal(0, raisedName.Count);
607+
608+
// Set it to another value.
609+
builder.Data = RichData.CreateBuilder();
610+
Assert.Equal(nameof(builder.Data), raisedName.Pop());
611+
Assert.Equal(0, raisedName.Count);
612+
}
613+
575614
private static void VerifyDescendentsShareRoot(RootedFileSystemDirectory directory)
576615
{
577616
foreach (var child in directory)

src/ImmutableObjectGraph.Generation/CodeGen+BuilderGen.cs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,12 @@ protected IReadOnlyList<MemberDeclarationSyntax> CreateMutableProperties()
193193
foreach (var field in this.generator.applyToMetaType.LocalFields)
194194
{
195195
var thisField = Syntax.ThisDot(field.NameAsField);
196+
var optionalFieldNotYetDefined = SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, Syntax.OptionalIsDefined(thisField));
196197
var getterBlock = field.IsGeneratedImmutableType
197198
? SyntaxFactory.Block(
198199
// if (!this.fieldName.IsDefined) {
199200
SyntaxFactory.IfStatement(
200-
SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, Syntax.OptionalIsDefined(thisField)),
201+
optionalFieldNotYetDefined,
201202
SyntaxFactory.Block(
202203
// this.fieldName = this.immutable.fieldName?.ToBuilder();
203204
SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
@@ -213,17 +214,32 @@ protected IReadOnlyList<MemberDeclarationSyntax> CreateMutableProperties()
213214
SyntaxFactory.ArgumentList())))))),
214215
SyntaxFactory.ReturnStatement(Syntax.OptionalValue(thisField)))
215216
: SyntaxFactory.Block(SyntaxFactory.ReturnStatement(thisField));
216-
var setterBlock = SyntaxFactory.Block(
217-
SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
218-
SyntaxKind.SimpleAssignmentExpression,
217+
var setterCondition = field.IsGeneratedImmutableType
218+
? SyntaxFactory.BinaryExpression(
219+
SyntaxKind.LogicalOrExpression,
220+
optionalFieldNotYetDefined,
221+
SyntaxFactory.BinaryExpression(
222+
SyntaxKind.NotEqualsExpression,
223+
Syntax.OptionalValue(thisField),
224+
SyntaxFactory.IdentifierName("value")))
225+
: SyntaxFactory.BinaryExpression(
226+
SyntaxKind.NotEqualsExpression,
219227
thisField,
220-
SyntaxFactory.IdentifierName("value"))),
221-
SyntaxFactory.ExpressionStatement(
222-
SyntaxFactory.InvocationExpression(
223-
SyntaxFactory.MemberAccessExpression(
224-
SyntaxKind.SimpleMemberAccessExpression,
225-
SyntaxFactory.ThisExpression(),
226-
OnPropertyChangedMethodName))));
228+
SyntaxFactory.IdentifierName("value"));
229+
var setterBlock = SyntaxFactory.Block(
230+
SyntaxFactory.IfStatement(
231+
setterCondition,
232+
SyntaxFactory.Block(
233+
SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
234+
SyntaxKind.SimpleAssignmentExpression,
235+
thisField,
236+
SyntaxFactory.IdentifierName("value"))),
237+
SyntaxFactory.ExpressionStatement(
238+
SyntaxFactory.InvocationExpression(
239+
SyntaxFactory.MemberAccessExpression(
240+
SyntaxKind.SimpleMemberAccessExpression,
241+
SyntaxFactory.ThisExpression(),
242+
OnPropertyChangedMethodName))))));
227243

228244
var property = SyntaxFactory.PropertyDeclaration(
229245
this.GetPropertyTypeForBuilder(field),

0 commit comments

Comments
 (0)