Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clang-format configs #323

Open
wants to merge 2 commits into
base: unstable
Choose a base branch
from
Open

Conversation

PingXie
Copy link
Member

@PingXie PingXie commented Apr 15, 2024

I have validated that these settings closely match the existing coding style with one major exception on BreakBeforeBraces, which will be Attach going forward. The mixed BreakBeforeBraces styles in the current codebase are hard to imitate and also very odd IMHO - see below

if (a == 1) { /*Attach */
}
if (a == 1 ||
    b == 2)
{ /* Why? */
}

Please do NOT merge just yet. Will add the github action next once the style is reviewed/approved.

@PingXie
Copy link
Member Author

PingXie commented Apr 15, 2024

@valkey-io/contributors @mattsta

@mattsta
Copy link

mattsta commented Apr 15, 2024

yeah, BreakBeforeBraces: Attach looks correct. Removing any custom indent matching or function art is cleaner. Cleaning up inconsistencies looks good even if it changes some of the current style decisions (which is the point of more stable auto-formatted styles!).

and if there is a need for specific visible alignment somewhere, just wrapping in ignore/resume blocks works:

/* clang-format off */
// my weird code i don't want the formatter to touch
/* clang-format on */

Sometimes wrapping byte tables or other bulk data in ignore blocks helps if the formatter tries to turn an 80 column array into 500 lines only having one element each or something else weird.

Most of the settings are already provided by the LLVM style preference from BasedOnStyle: LLVM (also see: clang-format -style=llvm -dump-config), but being explicit with extra options is always fine too.

extra note: may want to double check any recursive auto-formatting does not format the deps directory because that would probably be a big mess unnecessarily.

@madolson
Copy link
Member

Can you apply it on a file? That might be easier to check against too for sanity. Maybe something like module.c.

@madolson
Copy link
Member

The answer was that single lines attached and multi-lines don't attach. It seems like clang supports it with BraceWrappingAfterControlStatementStyle MultiLine. I came to like it more than attaching or detaching in all cases. I think this more closely matches the current style if we want to keep it.

Comment on lines +182 to +184
#define VALKEYMODULE_CTX_TEMP_CLIENT \
(1 << 6) /* Return client object to the pool \
when the context is destroyed */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very weird, not sure if we need to ignore this or fix it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's also a good example of why trailing line comments are bad in practice.

It's much cleaner to do:

/* comment for the next thing */
#define VALKEYMODULE_CTX_TEMP_CLIENT (1 << 6)

It would require manually fixing all those broken end-of-line comments though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised this even compiles. Don't you need to escape the new-line after ...CLIENT ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: quantified experiments in code-understanding concluded that people understand trailing-line comments more easily. Sorry, I learned that so long ago that I don't have a reference right now.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you need to escape the new-line after ...CLIENT ?

if you scroll far to the right, the \ is right-aligned at full line spec width (the github preview just has it out of scope with no wide scroll indicator)

experiments in code-understanding concluded that people understand trailing-line comments more easily.

seems illogical? vertical parsing is clearly superior.

also this example is weird because it's a macro. including a comment in-line with a macro means the comment is also being expanded into the macro replacement locations (which works, but is also unnecessary).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extremely well thought through 👍

Yeah, your 5 vs 6 example is good because it depends on the use case. It's nice seeing the vertical alignment to compare values, but the per-line comments overflow the viewport; while the 6 is easier to read the comments but takes an extra second to very 5->6->7 are in order.

Overall, going for nice machine style enforcing clean maintainable readability is always a win over "big programmer brain decide style decision per-line" (at least when working in groups and on projects that can live for decades, for single projects just do whatever, which is why it's always nice to have single projects too!).

overall these are just feedback ideas for whoever makes actual decisions around here 🦅

values!

This is also a bit of a weird/contrived example because technically these things should be enums and not defines anyway 🙃

oh glob i just looked and the enums in the code are all weird too. They are almost all anonymous typedef enum { a, b, c } name; so they won't show their fully type details in debuggers versus proper usage of typedef enum name { a, b, c } name; wheeeee:

src/$ rg "typedef enum" --stats

37 matches
37 matched lines
18 files contained matches

alignment

as for right-aligned continues, here's some live code found in the wild:

#define INSERT_SEP \   
    if (g->state[g->depth] == yajl_gen_map_key ||               \
        g->state[g->depth] == yajl_gen_in_array) {              \
        g->print(g->ctx, ",", 1);                               \
        if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1);               \
    } else if (g->state[g->depth] == yajl_gen_map_val) {        \
        g->print(g->ctx, ":", 1);                               \
        if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, " ", 1);                \
   }

#define INSERT_WHITESPACE                                               \
    if ((g->flags & yajl_gen_beautify)) {                                                    \
        if (g->state[g->depth] != yajl_gen_map_val) {                   \
            unsigned int _i;                                            \
            for (_i=0;_i<g->depth;_i++)                                 \
                g->print(g->ctx,                                        \
                         g->indentString,                               \
                         (unsigned int)strlen(g->indentString));        \
        }                                                               \
    }                               
                                     
#define ENSURE_NOT_KEY \                         
    if (g->state[g->depth] == yajl_gen_map_key ||       \
        g->state[g->depth] == yajl_gen_map_start)  {    \
        return yajl_gen_keys_must_be_strings;           \
    }                                                   \ 

/* initialize a bytestack */
#define yajl_bs_init(obs, _yaf) {               \
        (obs).stack = NULL;                     \
        (obs).size = 0;                         \
        (obs).used = 0;                         \
        (obs).yaf = (_yaf);                     \
    }                                           \


/* initialize a bytestack */
#define yajl_bs_free(obs)                 \
    if ((obs).stack) (obs).yaf->free((obs).yaf->ctx, (obs).stack);

#define yajl_bs_current(obs)               \
    (assert((obs).used > 0), (obs).stack[(obs).used - 1])

#define yajl_bs_push(obs, byte) {                       \
    if (((obs).size - (obs).used) == 0) {               \
        (obs).size += YAJL_BS_INC;                      \
        (obs).stack = (obs).yaf->realloc((obs).yaf->ctx,\
                                         (void *) (obs).stack, (obs).size);\
    }                                                   \
    (obs).stack[((obs).used)++] = (byte);               \
}

and here's a better auto-format cleaned-up version (still not perfect; executable code statements in defines should be in a do { } while (0); loop, etc, but that's behavior/correctness issues instead of formatting):

#define INSERT_SEP                                                             \
    if (g->state[g->depth] == yajl_gen_map_key ||                              \
        g->state[g->depth] == yajl_gen_in_array) {                             \
        g->print(g->ctx, ",", 1);                                              \
        if ((g->flags & yajl_gen_beautify))                                    \
            g->print(g->ctx, "\n", 1);                                         \
    } else if (g->state[g->depth] == yajl_gen_map_val) {                       \
        g->print(g->ctx, ":", 1);                                              \
        if ((g->flags & yajl_gen_beautify))                                    \
            g->print(g->ctx, " ", 1);                                          \
    }                    
                     
#define INSERT_WHITESPACE                                                      \
    if ((g->flags & yajl_gen_beautify)) {                                      \
        if (g->state[g->depth] != yajl_gen_map_val) {                          \
            unsigned int _i;                                                   \
            for (_i = 0; _i < g->depth; _i++)                                  \
                g->print(g->ctx, g->indentString,                              \
                         (unsigned int)strlen(g->indentString));               \
        }                                                                      \
    }         
                   
#define ENSURE_NOT_KEY                                                         \
    if (g->state[g->depth] == yajl_gen_map_key ||                              \
        g->state[g->depth] == yajl_gen_map_start) {                            \
        return yajl_gen_keys_must_be_strings;                                  \
    }                 

/* initialize a bytestack */
#define yajl_bs_init(obs, _yaf)                                                \
    {                                                                          \
        (obs).stack = NULL;                                                    \
        (obs).size = 0;                                                        \
        (obs).used = 0;                                                        \
        (obs).yaf = (_yaf);                                                    \
    }

/* initialize a bytestack */
#define yajl_bs_free(obs)                                                      \
    if ((obs).stack)                                                           \
        (obs).yaf->free((obs).yaf->ctx, (obs).stack);

#define yajl_bs_current(obs)                                                   \
    (assert((obs).used > 0), (obs).stack[(obs).used - 1])

#define yajl_bs_push(obs, byte)                                                \
    {                                                                          \
        if (((obs).size - (obs).used) == 0) {                                  \
            (obs).size += YAJL_BS_INC;                                         \
            (obs).stack = (obs).yaf->realloc((obs).yaf->ctx,                   \
                                             (void *)(obs).stack, (obs).size); \
        }                                                                      \
        (obs).stack[((obs).used)++] = (byte);                                  \
    }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Speaking of

big programmer brain decide style decision per-line

see https://en.wikipedia.org/wiki/Donald_Knuth and https://en.wikipedia.org/wiki/Literate_programming

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just an automation tool doing its magic.

I would prefer not having trailing comments but I don't know if clang-format can handle that.

clang-format is the best free tool that I know of so I am willing to work with its limitations in exchange of a consistent style (even if it is not my favorite). In other words, you can say my bar is low, just "consistency" :-)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we can decide the our line limit is longer than 80, which is a very old limitation dating back to CRT monitors and VI vs Emacs wars.
I can easily live with 120 or even 160 line limit.
To make a point my current screen is so wide (and curved) that most of this page is white space to either side and a narrow band of thread in the middle.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually like 80, it imposes a certain discipline. I'm OK with 120, but not 160. At 160 and at the font-size that I need, there isn't room for much else on my screen, and I like to look at references and stuff without hiding the actual code.

Comment on lines -1085 to +1078
* ValkeyModule_ChannelAtPosWithFlags(ctx, 1, VALKEYMODULE_CMD_CHANNEL_SUBSCRIBE | VALKEYMODULE_CMD_CHANNEL_PATTERN);
* ValkeyModule_ChannelAtPosWithFlags(ctx, 1, VALKEYMODULE_CMD_CHANNEL_PUBLISH);
* ValkeyModule_ChannelAtPosWithFlags(ctx, 1, VALKEYMODULE_CMD_CHANNEL_SUBSCRIBE |
* VALKEYMODULE_CMD_CHANNEL_PATTERN); ValkeyModule_ChannelAtPosWithFlags(ctx, 1, VALKEYMODULE_CMD_CHANNEL_PUBLISH);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is another weird side effect, it's trying to make it like a real sentence, when we just want it to look like commented code. We'll probably want to wrap all of the module docs with this. We probably want to take extra care here.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, fix is either allow the long lines to linger (but they were probably written too long in the first place) or run around and fix them all into the project style width requirements 🤷

or go for extreme reduction and rename ValkeyModule -> VKM everywhere to help with shorter lines 🙈

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-format doesn't seem to know how to format code embedded in the comments so yeah we will have to manually format it for once. But there shouldn't be more work after that.

SpacesInSquareBrackets: false
ReflowComments: true
CommentPragmas: '^\\s*\\*'
InsertBraces: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
InsertBraces: true
InsertBraces: false

I don't feel like we should force this, I see it is causing a lot of changes.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"optional syntax" in different places like un-braced if/while/do/for statements are an easy way to have bugs slip in by accident so it probably shouldn't be allowed. Much better for standard reliability development practices to enforce braces everywhere.

Typical arguments against it are:

  • but we enforce it with formatting (weak argument in a non-space-sensitive language)
  • but i don't want to (weak argument)
  • but i want statements only on one line (weak argument, makes updating/refactoring difficult)

everybody, at some point, has done a change like this when in a hurry and broken something. The easy fix is to just not allow it and enforce it with coding styles:

if (thing)
  a += 1;

if (thing)
  printf("CHECK: %d\n", a);
  a += 1;

Or, you have a one line if statement and you want to paste something else in there for structure, so you have to re-add braces when it would cost nothing to just use them in the first place?

Also without braces, it makes quick "capture braces for cut/paste" moving/refactoring more difficult too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the good side, the existing code is so totally random with its braces that the programmer is probably ready for this sh*t.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (thing)
  a += 1;

vs

if (thing) a+= 1;

Is actually the format I use fairly frequently, since I think when used appropriately it makes code a lot more readable. A case in module.c was:

        if (clusterNodeIsMyself(node)) *flags |= VALKEYMODULE_NODE_MYSELF;
        if (clusterNodeIsMaster(node)) *flags |= VALKEYMODULE_NODE_PRIMARY;
        if (clusterNodeIsSlave(node)) *flags |= VALKEYMODULE_NODE_REPLICA;
        if (clusterNodeTimedOut(node)) *flags |= VALKEYMODULE_NODE_PFAIL;
        if (clusterNodeIsFailing(node)) *flags |= VALKEYMODULE_NODE_FAIL;
        if (clusterNodeIsNoFailover(node)) *flags |= VALKEYMODULE_NODE_NOFAILOVER;

I could give it up though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would never complain about the last example in a code review.

If you asked me, I would vote against enforcing braces (or the equivalent for each language), but I know that nearly every coding standard in the world does insist on them.

If you are being forced to use braces, you can always write these examples as

if (x) { *flags |= y; }

Sadly, that too is disallowed by every set of coding standards I have ever seen.

The best advice I have ever seen came from a paper I read in the 90's. It recognized that different people respond in different ways to the same thing, so we should store all programs in a canonical format, but display them and edit them in whatever format the user likes. Sadly, even today our formatters are not good enough to support this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warnings like that scare me.

If for some reason we choose to enable that option, then we really should take the recommended extra care. But that would require that we get some kind of alert when it happens. Does such an alert get generated by the formatter?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@madolson "I don't feel like we should force this, I see it is causing a lot of changes." lets rip the band-aid once...
besides, git now days knows to look behind marked commits and blame the correct person around the re-formatted code

So lets decide on what we like and less on what we have

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is more that a lot of people prefer this. I don't like forcing style that is harder to read. I don't like forcing the braces.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to introduce this incrementally, we should start with more liberal rules. Then we can make them more strict later on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to introduce this incrementally, we should start with more liberal rules. Then we can make them more strict later on.

I like this.

@daniel-house
Copy link
Member

daniel-house commented Apr 17, 2024

Can you apply it on a file? That might be easier to check against too for sanity. Maybe something like module.c.

Can you apply it on a paragraph from inside your favorite editor?

I currently do all my code-formatting inside Eclipse using a minor tweak of the default K&R formatting rules. I can highlight a few lines, then hit ctrl-shift-f, and see if I like the result. In rare cases the result is unacceptable and I edit the code a little bit more by hand. This means I can get automated formatting without affecting any of the code I didn't change, so the code review doesn't report a lot of lines changed when I never touched them.

Eclipse: https://marketplace.eclipse.org/free-tagging/clang-format

Vim: see the Vim section of https://clang.llvm.org/docs/ClangFormat.html

@mattsta
Copy link

mattsta commented Apr 17, 2024

Can you apply it on a paragraph from inside your favorite editor?

That's another approach reasonable too: only require formatting on updated things.

the formatter can be made diff/patch-aware so it only checks changed code: https://clang.llvm.org/docs/ClangFormat.html#script-for-patch-reformatting

@madolson madolson added the major-decision-pending Needs decision by core team label Apr 21, 2024
@PingXie
Copy link
Member Author

PingXie commented Apr 24, 2024

Can you apply it on a paragraph from inside your favorite editor?

Not sure if you are looking for an example or it is more about a feature but yes many editors allow to you change selected text only.

only require formatting on updated things.

I think we have already gone past that point. The whole rename exercise pretty much killed half of the code history (and more is coming). I would say we push forward now and reformat the whole codebase to whatever we like. I am worried that the window for reformatting is closing with us merging more PRs.

Can we take a vote on the two decisions below?

  1. clang-format the entire codebase and create an automation via github actions for every merge (Valkey code only)
  2. the exact style to use

I am willing to compromise on 2 to get 1.

@valkey-io/core-team

@zuiderkwast
Copy link
Contributor

clang-format the entire codebase

I would like to se a diff of the whole change to decide if I like it or not.

If it's a lot of reformatting, then I'd prefer only doing it changed lines.

The rebranding didn't touch many lines. For example, in src/server.c, we only changed 4.5% of the lines since forking. The blame info is still usable.

the exact style to use

I think we should use style rules that cause the least changes to the code base. Why? We already have conventions, even though they're not written down and are not enforced by tools.

For example, this style is fairly common in the code base so I think we should keep it, without braces and without extra newlines:

    if (x) flags |= FLAG_X;
    if (y) flags |= FLAG_Y;
    ...

I'd be fine with enclosing blocks of such code with /* clang-format off */ and /* clang-format on */ comments though. The same probably applies to many long printf-like lines (INFO command), especially where we use the FMTARGS macro.

@daniel-house
Copy link
Member

I would feel much better if, instead of auto-formatting every commit, we added a new format-test to the CI pipeline. This test would fail if applying the auto-format changed anything.

My thinking is, first and foremost, we are smarter than the auto-formatter. It will all be code reviewed by humans any way, and if the humans approve it then it shouldn't be changed by the formatter. If we review it after the auto-formatter hits it, and we don't like the way it looks, it may be difficult to recognize that the ugliness was introduced by the auto-formatter. On the other hand, if the author knowingly submitted code that the auto-formatter would change, the author would be required to flag it with the dont-format-this annotation, which would in turn alert reviewers that the author intentionally did something unusual. Ideally, we should almost always accept the results of the auto-formatter, but still have room to do those rare things that we do best.

This approach also ensures that the author of a change looks at the after-formatted code and has a chance to improve it before wasting a reviewer's time.

@daniel-house
Copy link
Member

Please make sure the auto-format rules are idempotent. I have seen some formatters that don't like their own output. If we are going to auto-format the entire code base, we could run a simple test to ensure that at least the current result is a fixed-point of the auto-format function.

@PingXie
Copy link
Member Author

PingXie commented May 7, 2024

I would like to se a diff of the whole change to decide if I like it or not.

As you wish :-)

src/dict.c Show resolved Hide resolved
@@ -148,7 +147,7 @@
dictEntry *samples[server.maxmemory_samples];

int slot = kvstoreGetFairRandomDictIndex(samplekvs);
count = kvstoreDictGetSomeKeys(samplekvs,slot,samples,server.maxmemory_samples);
count = kvstoreDictGetSomeKeys(samplekvs, slot, samples, server.maxmemory_samples);

Check failure

Code scanning / CodeQL

Use of a broken or risky cryptographic algorithm

This file makes use of a broken or weak cryptographic algorithm (specified by [call to kvstoreDictGetSomeKeys](1)).
Copy link

codecov bot commented May 7, 2024

Codecov Report

Attention: Patch coverage is 77.72480% with 654 lines in your changes are missing coverage. Please review.

Project coverage is 68.05%. Comparing base (c7ad9fe) to head (7d728c7).
Report is 1 commits behind head on unstable.

❗ Current head 7d728c7 differs from pull request most recent head fc8962d. Consider uploading reports for the commit fc8962d to get more accurate results

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable     #323      +/-   ##
============================================
- Coverage     69.81%   68.05%   -1.77%     
============================================
  Files           109      109              
  Lines         61801    63657    +1856     
============================================
+ Hits          43149    43321     +172     
- Misses        18652    20336    +1684     
Files Coverage Δ
src/acl.c 88.00% <ø> (-0.98%) ⬇️
src/asciilogo.h 100.00% <100.00%> (ø)
src/cluster_legacy.c 82.46% <ø> (-3.75%) ⬇️
src/config.c 77.03% <ø> (-0.78%) ⬇️
src/connection.h 93.58% <100.00%> (ø)
src/connhelpers.h 100.00% <100.00%> (ø)
src/crc16.c 100.00% <100.00%> (ø)
src/crc64.c 100.00% <100.00%> (ø)
src/crccombine.c 100.00% <100.00%> (ø)
src/debug.c 53.41% <ø> (-0.06%) ⬇️
... and 96 more

src/networking.c Outdated
Comment on lines 1243 to 1245
if (listLength(src->reply)) {
listJoin(dst->reply, src->reply);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like every other change is this. I feel strongly now that we shouldn't enforce that everything is wrapped, because we can skip it right?

@madolson
Copy link
Member

madolson commented May 7, 2024

Reposting an earlier comment:

The answer was that single lines attached and multi-lines don't attach. It seems like clang supports it with BraceWrappingAfterControlStatementStyle MultiLine. I came to like it more than attaching or detaching in all cases. I think this more closely matches the current style if we want to keep it.

That means:

if (foo) {

and

if (foo && whateverthisthingiswaytoolongomgwhatareyoudoingcomeupwithabettername ||
    is notanybetter)
{

Copy link
Contributor

@zuiderkwast zuiderkwast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed from "functions.c" to "object c" and put some comments.

In general it is good changes but I think we should insert clang-format off in selected places, like help text output.

src/functions.c Outdated Show resolved Hide resolved
src/latency.c Outdated Show resolved Hide resolved
src/listpack.c Outdated Show resolved Hide resolved
src/listpack.c Outdated Show resolved Hide resolved
src/module.c Outdated Show resolved Hide resolved
src/object.c Outdated Show resolved Hide resolved
src/object.c Outdated Show resolved Hide resolved
src/object.c Outdated Show resolved Hide resolved
src/object.c Show resolved Hide resolved
src/object.c Outdated Show resolved Hide resolved
src/t_string.c Outdated Show resolved Hide resolved
@zuiderkwast
Copy link
Contributor

I went through the whole diff and identified where I think we need to disable the automatic format. I added /* clang-format off */ annotations in #468. We can merge it as a preparation, before the run clang-format. Feel free to add more exceptions.

With these exceptions, I'm fine with running clang-format on the rest. 👍

@hwware
Copy link
Member

hwware commented May 8, 2024

I think we need to clarify under which condition or provide a reference link , developer should use /* clang-format off */ flag?
I think we should describe this in some places so that all people can follow this rule

zuiderkwast added a commit that referenced this pull request May 8, 2024
This is a preparation for adding clang-format.

These comments prevent automatic formatting in some places. With these
exceptions, we will be able to run clang-format on the rest of the code.

This is a preparation for #323.

---------

Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
PenaltyExcessCharacter: 100
MaxEmptyLinesToKeep: 2
BreakBeforeBraces: Attach
AllowShortIfStatementsOnASingleLine: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem like true is one of the possible values of this config. https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowshortifstatementsonasingleline

If we want to allow it for if without else, we could use

Suggested change
AllowShortIfStatementsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: WithoutElse

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should also enable

AllowShortCaseLabelsOnASingleLine: true

@PingXie
Copy link
Member Author

PingXie commented May 13, 2024

sorry - human error. will re-open

Signed-off-by: Ping Xie <pingxie@google.com>
@PingXie PingXie reopened this May 13, 2024
@PingXie
Copy link
Member Author

PingXie commented May 13, 2024

single lines preserved. changes are mostly around spaces (missing spaces, extra spaces, trailing spaces, etc).

src/server.c Outdated
Comment on lines 3422 to 3291
if (server.current_client &&
server.current_client->cmd &&
server.current_client->cmd->flags & CMD_TOUCHES_ARBITRARY_KEYS)
{
if (server.current_client && server.current_client->cmd &&
server.current_client->cmd->flags & CMD_TOUCHES_ARBITRARY_KEYS) {
transaction = 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to the attach multiline rule?

In general, I think it's much better now and the total changed lines are much less: 30k instead of 40k.

Btw, you didn't commit the clang format config file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added .clang-format.

What happened to the attach multiline rule?

it is attached, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I thought we wanted to attach single line but detach when multiline, BraceWrappingAfterControlStatementStyle MultiLine. That was the old convention anyway and I think most of the code followed this style, but I may have missed some discussion here and it's no big deal for me. I just noticed the change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. We will always attach.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was noticing the number of multi-line control statements has gone down significantly, so attaching the braces probably is just a lot less important.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, anyway, my concern was always that there's no indentation difference between secondlongline and thirdlongline in the example below, but now I've come to the conclusion that this is never really a problem. The important thing is that it's easy to see where the whole if starts and ends (}).

if (alonglongline ||
    secondlongline) {   // <-- 
    thirdlongline;      // <-- same indentation
    morelines;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that's strange. Most formatters that I have seen indent secondlongline one more time.

size_t
lzf_compress (const void *const in_data, size_t in_len,
void *out_data, size_t out_len);
size_t lzf_compress(const void *const in_data, size_t in_len, void *out_data, size_t out_len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .clang-format-ignore file I added in the other PR didn't work?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm - don't know why. let me revert all changes and reapply the formatting.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think my clang-format is too old. It is 14.0. I have been getting all kinds of errors when trying to update it on my machines. Will need to find a different machine and try again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a problem for users I suppose. An old version reformats lots of files and it gets committed. We could add the comment /* clang-formt off */ in all these files instead if it's safer.

karthyuom pushed a commit to karthyuom/valkey that referenced this pull request May 13, 2024
This is a preparation for adding clang-format.

These comments prevent automatic formatting in some places. With these
exceptions, we will be able to run clang-format on the rest of the code.

This is a preparation for valkey-io#323.

---------

Signed-off-by: Viktor Söderqvist <viktor.soderqvist@est.tech>

Signed-off-by: Karthick Ariyaratnam <karthyuom@gmail.com>
Signed-off-by: Ping Xie <pingxie@google.com>
@daniel-house
Copy link
Member

daniel-house commented May 13, 2024

Reposting an earlier comment:

The answer was that single lines attached and multi-lines don't attach. It seems like clang supports it with BraceWrappingAfterControlStatementStyle MultiLine. I came to like it more than attaching or detaching in all cases. I think this more closely matches the current style if we want to keep it.

That means:

if (foo) {

and

if (foo && whateverthisthingiswaytoolongomgwhatareyoudoingcomeupwithabettername ||
    is notanybetter)
{

So much for consistency.

Comment on lines 44 to 45
/* Everything below this line is automatically generated by
* generate-fmtargs.py. Do not manually edit. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is automatically generated, we need to fix the generator too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hehe, we can make the generator emit /* clang-format off */.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think that makes more sense than generating compliant code.

src/functions.c Outdated
" * ASYNC: Asynchronously flush the libraries.",
" * SYNC: Synchronously flush the libraries.",
"DUMP",
" Return a serialized payload representing the current libraries, can be restored using FUNCTION RESTORE command",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found it difficult to see what the problem was, so I will add some details. The original looks like this:

"    Return a serialized payload representing the current libraries, can be restored using FUNCTION RESTORE command",

After autoformatting it looks like this:

        "    Return a serialized payload representing the current libraries, can be restored using FUNCTION RESTORE "
        "command",

I agree that this is a step backward. Another fine example of why I would prefer that the formatting be done by the developer prior to commit, and any time the formatter actually changes something it fails that stage of the pipeline.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer that the formatting be done by the developer prior to commit, and any time the formatter actually changes something it fails that stage of the pipeline.

Yeah that's how it will work once we've formatted all the old code. IIUC.

We should fix long lines like that manually, preferably in separate PRs before we autoformat everything.

SpacesInSquareBrackets: false
ReflowComments: true
CommentPragmas: '^\\s*\\*'
InsertBraces: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warnings like that scare me.

If for some reason we choose to enable that option, then we really should take the recommended extra care. But that would require that we get some kind of alert when it happens. Does such an alert get generated by the formatter?

Comment on lines +182 to +184
#define VALKEYMODULE_CTX_TEMP_CLIENT \
(1 << 6) /* Return client object to the pool \
when the context is destroyed */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually like 80, it imposes a certain discipline. I'm OK with 120, but not 160. At 160 and at the font-size that I need, there isn't room for much else on my screen, and I like to look at references and stuff without hiding the actual code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
major-decision-pending Needs decision by core team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants