abap-cleaner icon indicating copy to clipboard operation
abap-cleaner copied to clipboard

Feature request: separate formatting rules for nested statements

Open Lightirius opened this issue 2 years ago • 2 comments

Hi. I would like to have an option for existing rules or completly separate rules for nested method calls, value statements etc.

For example I would like to have alignment like this:

  DATA(lo_foo) = NEW lcl_foo(
    iv_parameter1 = abap_true
    iv_parameter2 = abap_false
  ).
  DATA(lo_bar) = NEW lcl_bar(  ).

  DATA(lv_foor_result) = lo_foo->foo_method(
    iv_parameter1 = abap_true
    iv_parameter2 = abap_false
    iv_parameter3 = VALUE #( field1 = abap_true
                             field2 = abap_false )
    iv_parameter4 = lo_bar->bar_method( iv_parameter1 = abap_true
                                        iv_parameter2 = abap_false )
  ).

  lo_foo->foo_method(
    iv_parameter1 = abap_true
    iv_parameter2 = abap_false
    iv_parameter3 = VALUE #( field1 = abap_true
                             field2 = abap_false )
    iv_parameter4 = lo_bar->bar_method( iv_parameter1 = abap_true
                                        iv_parameter2 = abap_false )
  ).
  DATA(lv_test2) = VALUE lts_struct(
    field1 = abap_true
    field2 = abap_false
  ).

  DATA(ls_test) = VALUE lts_struct(
    field1 = lo_foo->foo_method(
               iv_parameter1 = abap_true
               iv_parameter2 = abap_false
               iv_parameter3 = VALUE #( field1 = abap_true
                                        field2 = abap_false )
               iv_parameter4 = lo_bar->bar_method( iv_parameter1 = abap_true
                                                   iv_parameter2 = abap_false ) )
    field2 = lo_bar->bar_method( iv_parameter1 = abap_true
                                 iv_parameter2 = abap_false )
  ).

  INSERT VALUE #(
    field1 = abap_true
    field2 = abap_false
  ) INTO TABLE lt_table.

Right now the closest looking thing I configured is this:

  DATA(lo_foo) = NEW lcl_foo( iv_parameter1 = abap_true
                              iv_parameter2 = abap_false ).
  DATA(lo_bar) = NEW lcl_bar( ).

  DATA(lv_foor_result) = lo_foo->foo_method(
      iv_parameter1 = abap_true
      iv_parameter2 = abap_false
      iv_parameter3 = VALUE #( field1 = abap_true
                               field2 = abap_false )
      iv_parameter4 = lo_bar->bar_method(
          iv_parameter1 = abap_true
          iv_parameter2 = abap_false ) ).

  lo_foo->foo_method(
      iv_parameter1 = abap_true
      iv_parameter2 = abap_false
      iv_parameter3 = VALUE #( field1 = abap_true
                               field2 = abap_false )
      iv_parameter4 = lo_bar->bar_method(
          iv_parameter1 = abap_true
          iv_parameter2 = abap_false ) ).
  DATA(lv_test2) = VALUE lts_struct( field1 = abap_true
                                     field2 = abap_false ).

  DATA(ls_test) = VALUE lts_struct( field1 = lo_foo->foo_method(
                                        iv_parameter1 = abap_true
                                        iv_parameter2 = abap_false
                                        iv_parameter3 = VALUE #( field1 = abap_true
                                                                 field2 = abap_false )
                                        iv_parameter4 = lo_bar->bar_method(
                                            iv_parameter1 = abap_true
                                            iv_parameter2 = abap_false ) )
                                    field2 = lo_bar->bar_method(
                                        iv_parameter1 = abap_true
                                        iv_parameter2 = abap_false ) ).

  INSERT VALUE #( field1 = abap_true
                  field2 = abap_false )
         INTO TABLE lt_table.

Main used rules are: "Close brackets at line end" "Align parameters and components" with configuration: align parameters and components

To clarify - there is no way (or i missed it) to:

  • control alignment of VALUE and similar statements like with "Functional call continue behind the call for up to X parameters" for methods
  • align closing brackets on new line for top statements and on line end for nested statements
  • always allow parameters left to assignment operator for top statements and never allow them for nested statements
  • align different number of method parameters behind functional call in top and nested statements

I propose the following additional options: Rule "Close brackets at line end":

  • Rename it to something like "Align closing brackets" and add two options:
  • Top statemets - possible values "at line end" "at new line" "keep as is"
  • Nested statements - possible values "at line end" "at new line" "keep as is" "same as top"

Rule "Align parameters and components"

  • Additional option "top VALUE statement (etc.): continue behind open bracket for up to X components"
  • Additional option "nested VALUE statement (etc.): continue behind open bracket for up to X components"
  • Split the option "Allow line starts left of assignment operator" into two options for top and nested statements
  • Split the option "Functional call: continue behind the call for up to X parameters" into two options for top and nested statments

Lightirius avatar Oct 20 '23 17:10 Lightirius

Hi Lightirius,

thanks for this thorough proposal! I must admit, I'm not quite sure which way to go:

  • on the one hand, particularly regarding the closing parentheses, I know some colleagues who favor this style, including some that have given clean code a lot of thought.
  • on the other hand, this goes against several agreed styleguide rules (Close brackets at line endKeep parameters behind the callIf you break, indent parameters under the callIndent and snap to tab regarding 4 spaces) and would add a lot of new options and therefore complexity (both on the UI and in the implementation) to this already quite complex rule – and anyway, what would be the argument why top statements should be treated differently from nested statements?

So, maybe a case for "discussion wanted"?

Kind regards, Jörg-Michael

jmgrassau avatar Oct 28 '23 08:10 jmgrassau

Hi Jörg-Michael, I understand that this is a big proposal that will introduce a lot of complexity and most of it goes against the SAP styleguide, so yes it needs a discussion.

My points are mostly subjective. They are based on the preference to minimize the amount of empty space on the left side of the code editor and (subjectively) more cleanly separate top and nested statements. If you strictly follow SAP recommended styleguide - VALUE statements, method calls and similar constructions can be pushed too far to the right. Personally, I see that as a bad style, because it forces you to constantly look to the right. ABAP is already somewhat verbose and some lines are already long.

As an example, there can be a VALUE statement for some BAPI structure. They can have A LOT of fields, so we have each field on a separate line. If you use inline declarations it can move all of the code too far to the right for the next 10-50 lines.

Somewhat exaggerated example, that fits into the recommended 120 columns limit:

  DATA(really_specific_variable_name) = VALUE zcl_class_with_types=>really_specific_type_name( fieldname1 = value1
                                                                                               fieldname2 = value2
                                                                                               fieldname3 = value3
                                                                                               fieldname4 = value4
                                                                                               fieldname5 = value5
                                                                                               fieldname6 = value6 ).

Right now in ABAP cleaner we already have some options that go against SAP styleguides and I don't think that some optional deviations are bad. For example, for method calls we already have configurable number of parameters to keep after the call, I don't see why not add an extra parameter for other constructions like VALUE NEW etc. It can be a simple checkbox "apply to VALUE and similar statements"

The point about closing bracket on the new line - In my opinion it allows you to clearly see the end of the long statement, but for nested statements it is too much, hence separate rules.

Points about the complete separation of rules for top and nested statements is mostly fine-tuning, and they might be too complex to implement\maintain\configure. (They are still less complex than some formatting tools for other languages)

Minimally, I would really love to see these options added:

  • Add ability to control the amount of components behind the open bracket for VALUE, NEW, etc. statements, similar to "Functional call continue behind the call for up to X parameters"
  • Apply "Allow line starts left of assignment operator" to VALUE, NEW, etc, statements (Can't test right now, but it might already work if long lines are wrapped)
  • Option to keep the closing bracket on the new line for multiline top statements (aka "the closing bracket with the dot")

Lightirius avatar Oct 28 '23 14:10 Lightirius