The current method used for avoiding cycles and duplicate printing, using index-based references, is not serving us well in the use case of StatePrinter combined with ApprovalTests as a way of ensuring object state doesn't change over time. If one new reference is added or removed somewhere 'early' in the object, the indices of all following references are incremented, making it very difficult to tell what really changed. For example, if we have this printed object:
Root = new RootObject()
{
_container = new Container(), ref: 1
{
_objects = new List<Object>()
{
[0] = new A(), ref: 0
{
}
}
_a = -> 0
}
_otherObject = new OtherObject()
{
_container = -> 1
}
[lots more objects with lots more references]
}
If the reference to the object A() is removed, all following reference indices will be decremented. When looking at the change to the object, there will be a diff for each line in the file that previously had a reference on it. For very large files (1000s of lines), it becomes tedious to spot the real change, especially if there are other real changes later in the file.
I propose a 'path-based' way of referencing instead. The above example would then look something like this:
Root = new RootObject()
{
_container = new Container()
{
_objects = new List<Object>()
{
[0] = new A()
{
}
}
_a = -> Root._container._objects[0]
}
_otherObject = new OtherObject()
{
_container = -> Root._container
}
[lots more objects with lots more references]
}
With this approach, changes wouldn't ripple to unrelated objects like described above.
I'm not sure if it's better to do an absolute path from root (as shown above) or a relative path. Maybe that could be user-configurable. With relative paths, the above references could then look something like this._objects[0] and ^._container.
If I get the time, I might take a first stab at implementing this. I imagine it will require some fairly substantial changes in Introspector.
The current method used for avoiding cycles and duplicate printing, using index-based references, is not serving us well in the use case of StatePrinter combined with ApprovalTests as a way of ensuring object state doesn't change over time. If one new reference is added or removed somewhere 'early' in the object, the indices of all following references are incremented, making it very difficult to tell what really changed. For example, if we have this printed object:
If the reference to the object A() is removed, all following reference indices will be decremented. When looking at the change to the object, there will be a diff for each line in the file that previously had a reference on it. For very large files (1000s of lines), it becomes tedious to spot the real change, especially if there are other real changes later in the file.
I propose a 'path-based' way of referencing instead. The above example would then look something like this:
With this approach, changes wouldn't ripple to unrelated objects like described above.
I'm not sure if it's better to do an absolute path from root (as shown above) or a relative path. Maybe that could be user-configurable. With relative paths, the above references could then look something like
this._objects[0]and^._container.If I get the time, I might take a first stab at implementing this. I imagine it will require some fairly substantial changes in
Introspector.