rubberduck-vba / Rubberduck

Every programmer needs a rubberduck. COM add-in for the VBA & VB6 IDE (VBE).
https://rubberduckvba.com
GNU General Public License v3.0
1.91k stars 299 forks source link

Indenter line continuation, alignment #5852

Open nVenticDW opened 3 years ago

nVenticDW commented 3 years ago

Justification Given the code below, the indenter puts the equal sign in "=" under the equals before the continuation marker thereby defeating the object of a continuation marker and the line becomes more illegible than before indenting (such lines have to be manually unindented after indentation). Changing settings in alignment for the indenter makes no difference Note: MC_rStart and MC_cStart are constants (row 10, and column 6 in this case)

The code for the indenter (output is best displayed in the first screen shot):

With ActiveSheet
    .Range(.Cells(MC_rStart, MC_cStart), .Cells(TransLastRow, MC_cStart)).Value = _
                                                                                "=" & TransName & "!" & .Range(.Cells(MC_rStart, MC_cStart), .Cells(MC_rStart, MC_cStart)).Address(False, False)

Description Allow a setting where the continuation line just goes straight under the the start of the previous line, or perhaps allow offset by 4

Desired result 1

With ActiveSheet
    .Range(.Cells(MC_rStart, MC_cStart), .Cells(TransLastRow, MC_cStart)).Value = _
    "=" & TransName & "!" & .Range(.Cells(MC_rStart, MC_cStart), .Cells(MC_rStart, MC_cStart)).Address(False, False)

Alternative desired result:

With ActiveSheet
    .Range(.Cells(MC_rStart, MC_cStart), .Cells(TransLastRow, MC_cStart)).Value = _
        "=" & TransName & "!" & .Range(.Cells(MC_rStart, MC_cStart), .Cells(MC_rStart, MC_cStart)).Address(False, False)

Additional context Screenshots: indenter's output: Indenter bloating 1

desired result (output) Indenter bloating desired1

alternative desired result (output) Indenter bloating alt desired

Vogel612 commented 3 years ago

This might even count as a bug, because from how I understand it, the indenter behaviour that causes this is intended to align assignment values to one another.

That implies the indenter (incorrectly) parses the "=" as an assignment (which it is decidedly not) and thus aligns the equals signs to one another...

daFreeMan commented 3 years ago

Related, if not duplicates: #4632 & #4342

nVenticDW commented 3 years ago

Vogel612's post was onto something i thought, maybe it is some sort of bug or glitch which I was proposing a work around for, and so I attempted to further investigate since the indenter's behaviour makes it "dangerous" to run on a whole project, since it worsens the indenting

Firstly I added a constant

Const EQU as string ="="

and then I substituted "=" with EQU in the offending line. This attempted bypass had no effect.

I then tried to be bypass the "bug" by being more tricky Dim EQU As String EQU = "=" and subsituting the "=" in the offending line. Still no impact. The bug is, perhaps, too clever to be a bug. Maybe the indenter code is working properly, and a feature request is the only way to address this behaviour,

Then I tried changing the settings and I found I can make it do as per "desired result", if I switch off "Align continuations" Continuation Align

even with the original "=". I have no idea why I can make "desired result" work now, but I discovered the code readability is really bad for all the other continuations and the "alternative desired result", as in the original post, is my proposal for an option to make such continuations more readable, perhaps named "indent continuations" .

This testing is made more difficxult since I have over 20 modules, some very long, and every time I indent even one procedure it takes ages, since RD is probably reparsing everything. I just wish I could switch this reparsing off (or RD would limit its reparsing), though I understand why it is there since all the exact positions have changed and it is easier to code to reparse everything

Vogel612 commented 3 years ago

Curiously we have two unit-tests covering the use of continuations in declarations here and here which specify the first desired result as expected.

Something that will need to be investigated is the option of the With block confounding the indentation logic.

Really, the underlying issue is the fact that the indenter is a port of the original SmartIndenter and does not use the information we obtained from the parsing run in any way whatsoever. Instead the Indenter uses basic string manipulation and some complex logic, which is accordingly somewhat bug-prone and can be extremely complex to fix...

With the current implementation of the Indenter, this can possibly be quite an excessive amount of work. There have been suggestions of using the parse infrastructure for a reimplementation of the SmartIndenter features (c.f. #1288), but nothing has been finalized yet.

BZngr commented 3 years ago

There have been suggestions of using the parse infrastructure for a reimplementation of the SmartIndenter features

The SmartIndenter can be called upon to indent new code blocks introduced by Refactorings. So, while the SmartIndenter could use/leverage the parse infrastructure, there are still use cases where indentation of yet-to-be-parsed code is needed.

nVenticDW commented 3 years ago

Maybe the below helps any future research to look for source code for the complex logic, or for somebody who has similar issues:

Below is a list of alternatives for indentation looking for open source as well as others to use as a stop gap solution to support alternative 2, and also to allow fast indentation of a large project (without reparsing every time)

A. I have Andrew's AET indenter, really nice but causes issues on my 40 modules, and Andrew isn't supporting the product anymore and it is proprietary. it is good in most circumstances, no source code http://dailydoseofexcel.com/archives/2017/02/11/aet-vbe-tools/

B. indenter on Ron Bruin's web site. No settings are possible but it does, by default, alternative 2. A managed COM-. I have decided to use that. no source code https://www.rondebruin.nl/win/dennis/codemanager.htm

C. copy paste indenting using a module, I haven't tested but it is completely open source and therefore would support any bespoke indentation required, and could also be built upon. Maybe the logic is useful. https://en.wikibooks.org/wiki/Visual_Basic_for_Applications/VBA_Code_Indenter

D. smart indenter from the Charletsing www.cnblogs.com/Charltsing/p/SmartIndenter64.html (use chrome to translate), no better than others and no clear documentation, no source code https://blog.fearcat.in/a?ID=01550-1f04c558-1ba4-4b2e-949b-d5ebb312c8b9

E. The smart indenter from 2004 as contained in MacroToolsVBA as source code, but then that is also in RD zip file. https://github.com/vbatools/MacroToolsVBA

F. MZtools, but another a "big tool", and I prefer RD as the big tool

G. AutoMacro, Looks like another big tool

H. RD, running the indentation module by module once a year or less often and then manually change

I. Always move code to 32 bit excel machine and run the original indenter, but this probably has the same issues, being the original code source.

I looked at the source code of RD, and found a directory "Legacy" with the VBA code, which could be used to test and build a bespoke indenter without managing the whole RD and then used to make a running prototype. This is probably what was done as the indenter went into RD, so I ask myself why do this again? Also the forms don't have their frx binary versions and the forms themselves would have to be manually built. This lack of frx files is probably something to do with the original build language of the smart indenter. Even in RD version 1.4.3 or v2 alpha there were no frx files. However the form entries are described in the frm files so it should be possible to build them. Also the VBA has 32 bit APIs only so that would have to be updated.That is relatively easy.

The best alternatives (for me) are then

RonBruin's site code manager (B), noting there is no source code, so probably it is only a stop gap solution

Wait for RD to improve (the indentation and not autoparsing after a run) , This will probably be a year or two at least

and if one can't wait and needs bespoke indentation then:

Rebuild the legacy code from RD, the forms and then alter the APIs declarations to support 32 and 64 bit and then improve or Test and adopt the copy paste indenter (C)

Maybe that helps somebody with similar issues

awb95 commented 2 years ago

In think the Indenter does exactly what it should. As @nVenticDW discoverd the Indention ist dependent on the 'Align Continuation'-Setting

If Enabled the continuation is aligned behind the Assignment Operator (Not as assumend by @Vogel612 at the "="-String)

' Ignore Operator
Sub Test()
    foo = bar _
        & baz
End Sub

' Don't Ignore Operators
Sub a()
    foo = bar _
          & baz
End Sub

If 'Align Continuation' is diabled the continuation is Aligned to the parent indention-level (foo)

Sub Test()
    foo = bar _
    & baz
End Sub