Yes, but here's my hot take - what if you didn't have to edit the source code to debug it? Instead of chaining method calls you just assign to a temporary variable. Then you can set breakpoints and inspect variable values like you do normally without editing source.
It's not like you lose that much readability from
foo(bar(baz(c)))
c |> baz |> bar |> foo
c.baz().bar().foo()
t = c.baz()
t = t.bar()
t = t.foo()
I feel like a sufficiently good debugger should allow you to place a breakpoint at any of the lines here, and it should break exactly at that specific line.
I'm only familiar with C++, Python, and SQL. Neither GDB nor PDB helps here, and I've never heard of a SQL debugger that will break apart expressions and let you view intermediate query results.
You can use EXPLAIN and similar keywords to see the execution plans in common SQL database engines. In practice you don't really care about the actual intermediate data so it doesn't show it, usually it's enough to learn whether indices are used at every step.
But you could in many cases easily infer from the execution plan what a query would look like and fetch an intermediate set separately.
It’s been a while since I’ve used one, but I’m fairly sure the common debuggers for C#, F#, Rust and Java would all behave correctly when breakpointed like this.
Jetbrains Rider does this does for C# code (I think Visual Studio does as well). Its inlay hints feature will also show you hints with the result type of each line as the data is transformed. I haven't explicitly tested but I would imagine their IDEs for other languages behave the same.