Search code examples
cvisual-studio-codemacrosformatformatter

vscode cpptools customize format rule for C language macro to keep definition on same line


I have C language code as bellow:

  # define VAR(vartype, memclass) vartype
  
  VAR(float32, AUTOMATIC) var1;  // equal to "float32 var1;"

when I 'Format Document' in VSCODE, above VAR... code will be splited to 2 lines:

VAR(float32, AUTOMATIC)
var1; 

but I want it be only 1 line:

VAR(float32, AUTOMATIC) var1;

How could I implement it.


Solution

  • If you don't want lines to be changed by clang-format rules, one way is to surround them with marker lines as follows:

    // clang-format off
    VAR(float32, AUTOMATIC) var1;
    // clang-format on
    

    That gives reasonable fine-grained control over the reformatting feature but requires peppering your code with those marker comments. Additionally, and possibly unfortunately, it protects those lines from any formatting meaning that:

    VAR(float, AUTOMATIC)      leave_me_alone;     // blah blah.
    

    will not be reformatted to a (likely) more sensible:

    VAR(float, AUTOMATIC) leave_me_alone; // blah blah.
    

    To allow formatting but with special treatment for your macros, you can use the Macros stanza in the clang-format settings(1).

    For example, the C_Cpp:Clang_format_fallbackStyle setting in vscode is, by default, set to something compatible with Visual Studio (which is based on the LLVM style).

    By way of example, I modified it to include a "special dispensation" for your VAR macro as follows (see the Macros entry at the end - that's the only divergence from the default Visual Studio style):

    {
        "BasedOnStyle":"LLVM", "UseTab": "Never", "IndentWidth": 4,
        "TabWidth": 4, "BreakBeforeBraces": "Allman",
        "AllowShortIfStatementsOnASingleLine": false,
        "IndentCaseLabels": false, "ColumnLimit": 0,
        "AccessModifierOffset": -4, "NamespaceIndentation": "None",
        "FixNamespaceComments": true,
    
        "Macros": ["VAR(x,y)=x"]
    }
    

    Then I created a file junk.c with two macros so you can see the different effects:

    #define VAR(vartype, memclass) vartype
    #define XYZ(vartype, memclass) vartype
    
    VAR(float, AUTOMATIC)           leave_me_on_one_line;
    XYZ(float, AUTOMATIC) do_what_you_will_with_me;
    

    Upon formatting the file with ShiftAltF, the result is, as desired:

    #define VAR(vartype, memclass) vartype
    #define XYZ(vartype, memclass) vartype
    
    VAR(float, AUTOMATIC) leave_me_on_one_line;
    XYZ(float, AUTOMATIC)
    do_what_you_will_with_me;
    

    That method both avoids peppering your code with clang-format control lines and allows desired formatting to still be carried out on the macros.

    You can put as many macros as you like in the list but, if they become numerous, you may want to consider moving formatting control into a .clang-format file in your repo so that you're not continuously trying to update settings in that (ridiculously tiny) window it gives you:

    enter image description here

    Doing that will also allow you to use clang-format in headless builds (in checking mode) to ensure no badly-formatted code can "escape" to the master branch (assuming a well-set-up repository with merge checks and so on).


    (1) Note that this was introduced in clang-format-17 (see here) so, if you're not at that level or higher, you'll probably have to use the comment controls.