Clang Format: Add option to align types?

I’m not sure if this is even the right place to ask, I did a quick search looking for a clang-format specific list but couldn’t find one, does anyone know if there even is one?

I’m trying to add an option to Clang-Format that would allow users to align variables in structs/classes and functions based on the width of the type identifier.

Here’s a couple examples to better illustrate what I’m talking about:

typedef struct Unaligned_Struct {
int wat;
uint8_t huh;
uint64_t who;
} Unaligned_Struct;

int Unaligned_Average(int A, int B, int num) {
int Average = A + B;
int32_t Divided = Average / num;
return Divided;
}

vs

typedef struct Aligned_Struct {
int wat;
uint8_t huh;
uint64_t who;
} Aligned_Struct;

int Aligned_Average(int A, int B, int num) {
int Average = A + B;
int32_t Divided = Average / num;
return Divided;
}

I’m not sure if the formatting is showing up, so I geuss I’l have to describe it.

The Aligned blocks all of the variables have X number of spaces added between the type and the variable name, so that they’re all aligned in a single column.

it makes reading the code a lot easier, I’ve been doing thi manually with my code for a while, and Clang-Format not having this feature is the biggest reason I don’t currently use it.

As for my questions, they are:

How exactly do I do this?

Should I write a new enum (I’ve been thinking about calling it “AlignTypeDeclarationStyle”, but that seems a little clunky, and I’m not sure if it’s the best way to describe what exactly is going on)

and how exactly would I hook this into the Clang-Format library?

I’ve never contributed to the LLVM project before, I’ve read the documents a few times, and I’ve tried reading the code, but it’s very intertwined and it’s hard to drill down as deep as I need.

While I am not exactly able to help on the technical details as I’m also new on Clang grounds, if you or anyone else steps forward to implement this, I think it would be nice to early on consider a few more rules, such as:

  • Aligning the cv-qualifiers together and indent the real type name into a separate column
  • Within some reasonable boundary, align template arguments.

; Whisperity.

Hi Marcus,

There’s a way to do exactly what you described by setting AlignConsecutiveDeclarations to true in your .clang-format configuration. It is not clear whether you also want to set AlignConsecutiveAssignments true because all names in the examples have the same width, but you might also want to consider this option.

You can see more Clang-Format options and their descriptions in the documentation: https://clang.llvm.org/docs/ClangFormatStyleOptions.html

-Kirill

While I am not exactly able to help on the technical

> details as I’m also new on Clang grounds, if you or anyone
> else steps forward to implement this, I think it would be
> nice to early on consider a few more rules, such as:
> • Aligning the cv-qualifiers together and indent the real
> type name into a separate column

Do you mean something like this:

   //cv-qualifiers type varid
   //------------- ---- -----
     const int ci;
                         int i;
     const T<int,char> tic;

?

> • Within some reasonable boundary, align template
> arguments.

A problem with OP requirements and the above is deciding the
"reasonable boundary". For example, if the last line in the
above example were:

SomeLongTemplateName<SomeLongTemplateArg1,SomeLongTemplateArg2,...>

then there'd be a problem finding enough room one 1 line to
contain the whole declaration.

OTOH, the "reasonable boundary" problem largely disappears
if the declaration is "structure aligned" over several lines
just as now, most people "structure align" compound
statements over several lines. For example, instead of:

   if(C1)S1;else if(C2)S2;else S3;

most people "structure align" the if statement to:

   if(C1)
     S1;
   else if(C2)
     S2;
   else
     S3;

where the keywords (the most important part of the
structure), are all aligned in the same leftmost column and
the "details" (the sub-statements in the branches of the if)
are indented right to signify their lesser importance.

Similarly, the declarations could be "structure aligned" by
aligning the most important part of the declaration in the
leftmost column and the lesser import parts indented right.
For example:

     SomeLongTemplateName1
     < SomeLongTemplateArg1_1
     , SomeLongTemplateArg1_2
     >
     SomeCvQuals1
   SomeLongVarName2
     ;
     SomeLongTemplateName2
     < SomeLongTemplateArg2_1
     , SomeLongTemplateArg2_2
     >
     SomeCvQuals2
   SomeLongVarName2
     ;

Unfortunately, I don't know how to do this with clang-format
:frowning:

-regards,
Larry

Another issue that we should handle, tho tangential is that preprocessor blocks aren't formatted properly at all.

Example:

#if (defined(__UNIX__))
#define _FILE_OFFSET_BITS 64
#elif (defined _WIN32)
#define _UNICODE
#endif

and let's say we're compiling on a UNIX platform, so the first branch of the preprocessor directive is enabled, but not the second.

Only the enabled block would actually be formatted, the disabled block is completely ignored.

I'm not sure if this is just because the formatter is running after the preprocessor, or if it's a lot deeper than that, and Clang is removing the unavailable preprocessor tokens before anyone else has access to it?

if it's the latter, it could require a LOT of work to make it right...