florianschanda / miss_hit

MATLAB Independent, Small & Safe, High Integrity Tools - code formatter and more
GNU General Public License v3.0
158 stars 21 forks source link

indentation problem in nested functions with line continuations #245

Open Sec-ant opened 2 years ago

Sec-ant commented 2 years ago

MISS_HIT Component affected Please choose one from:

Your MATLAB/Octave environment

Your operating system and Python version

Describe the bug When I use mh_style with --fix option to style the following code

a = b(...
    c(...
    d(...
    e(...
    f(...
    g(...
    h...
    )...
    )...
    )...
    )...
    )...
    );

the output will be

a = b( ...
      c( ...
      d( ...
      e( ...
      f( ...
      g( ...
      h ...
     ) ...
     ) ...
     ) ...
     ) ...
     ) ...
     );

which is not a final steady indentation style and can be further styled multiple times till

a = b( ...
      c( ...
        d( ...
          e( ...
            f( ...
              g( ...
                h ...
               ) ...
             ) ...
           ) ...
         ) ...
       ) ...
     );

I'm assuming this is not intended and there may be some problem when calculating the indentation in this kind of nested functions with line continuations?

Sec-ant commented 2 years ago

And this kind of line continuations will just work fine (however the github matlab code syntax highlighting seems to be broken here):

before:

a = b...
    (c...
    (d...
    (e...
    (f...
    (g...
    (h...
    )...
    )...
    )...
    )...
    )...
    );

after:

a = b ...
    (c ...
     (d ...
      (e ...
       (f ...
        (g ...
         (h ...
         ) ...
        ) ...
       ) ...
      ) ...
     ) ...
    );
florianschanda commented 2 years ago

Yes, this is a known issue (see https://github.com/florianschanda/miss_hit/blob/master/CHANGELOG.md#tooling)

The way the indenter and pretty printer works is weird, and that largely explains this behaviour. It generally works by just adding or removing a few spaces; plus line continuations are really awkward in MATLAB anyway, and my handling of them is not ideal either.

I do plan to produce a totally new (ast-based) pretty printer; I just need to work out how to correctly deal with comments. But I can look at this case and see if I can maybe fix something, but please don't expect too much in the short term...

Sec-ant commented 2 years ago

Got it, no hurry. It's already an excellent work and fits my needs. Thanks!

florianschanda commented 2 years ago

I have a guess what is happening; the line continuation will be based on where the opening brace is; but we use the un-fixed position for determining the column number not the fixed one.

florianschanda commented 2 years ago

Ugh, as expected it's nasty. So the continuation is of course based on the last encountered bracket and we derive the indentation based on it's (fixed) location. But this logic only works if the bracket is the first thing in a line.

This will be very nasty to fix, but I will see what I can do.

Sec-ant commented 2 years ago

Ugh, as expected it's nasty. So the continuation is of course based on the last encountered bracket and we derive the indentation based on it's (fixed) location. But this logic only works if the bracket is the first thing in a line.

This will be very nasty to fix, but I will see what I can do.

👍 Good to know the reason!

And I find another case where similar problem occurs, I'm not sure if it fits your explanation regarding if the bracket is the first thing in a line:

a = [
b( ...
c, ...
d ...
)
];

format once:

a = [
     b( ...
  c, ...
  d ...
 )
    ];

twice:

a = [
     b( ...
       c, ...
       d ...
      )
    ];

Yet the following code will only need once:

            b( ...
        c, ...
    d ...
);
florianschanda commented 2 years ago

Yep, same thing, same issue. So there is three ways of fixing this, all with immense down-sides:

That said, I have totally re-written the fixer one before, so maybe it's time to re-design again with this kind of issue in mind.

I'll file the test-cases you made (thanks btw) and will keep this open, but nothing will happen this year pretty sure.

florianschanda commented 2 years ago

Maybe I will do option 2, but as an additional option (i.e. non-default behaviour), just in case somebody is willing to pay the performance hit.