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 5 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.

If you have to scroll all the way to the maximum line width in order to find something

It's kinda an artifact of somebody setting the line width unnaturally long too. Normally you just set 80 chars and everything looks fine (and normally we don't develop in github quoted preview blocks etc).

As for end of line comments, here we go using standard tools:
Screenshot 2024-04-17 at 12 55 13
Screenshot 2024-04-17 at 12 55 04

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I don't believe anyone would write end-of-line comments like that. That looks like a straw-man argument to me.

Suppose the original code looks like this:

#define VALKEYMODULE_CTX_TEMP_CLIENT (1 << 6) /* Return client object to the pool  when the context is destroyed */
  1. This is already terrible code!

  2. Yes, this would look MUCH better:

/* Return client object to the pool  when the context is destroyed */
#define VALKEYMODULE_CTX_TEMP_CLIENT (1 << 6)
  1. If it is going to be auto-formatted, then this would be horrible but tolerable for me:
#define VALKEYMODULE_CTX_TEMP_CLIENT \
    (1 << 6) /* Return client object to the pool \
                    when the context is destroyed */

But I would much prefer this horrible result:

#define VALKEYMODULE_CTX_TEMP_CLIENT               \
    (1 << 6) /* Return client object to the pool   \
                    when the context is destroyed */
  1. This still feels like a straw-man to me. Even a modestly smarter formatter should give
12345678901234567890123456789012345678901234567890123456789012345678901234567890

#define VALKEYMODULE_CTX_TEMP_CLIENT (1 << 6) /* Return client object to the \
                                                 pool when the context is    \
                                                 destroyed */

Note: the first line is a ruler. It is exactly 80 characters long.

  1. Is (4) more readable than (2)? That probably depends on both the context and the reader. Consider this context:
12345678901234567890123456789012345678901234567890123456789012345678901234567890

#define VALKEYMODULE_CTX_JUNK        (1 << 5) /* Do something with junk objects. */
#define VALKEYMODULE_CTX_TEMP_CLIENT (1 << 6) /* Return client object to the pool when the context is destroyed */
#define VALKEYMODULE_CTX_TRASH       (1 << 7) /* Don't forget to take out the trash every Thursday night. */

It violates the 80 character rule. In this case, I would say violating the rule is justified.

  1. Would you prefer this?
/* Do something with junk objects. */
#define VALKEYMODULE_CTX_JUNK (1 << 5)

/* Return client object to the pool when the context is destroyed */
#define VALKEYMODULE_CTX_TEMP_CLIENT (1 << 6)

/* Don't forget to take out the trash every Thursday night. */
#define VALKEYMODULE_CTX_TRASH (1 << 7)
  1. In summary,
  • Communication is HARD.
  • Guidelines are good, absolute rules are bad.
  • Context is critical.
  • Different people respond in different ways to the same thing.

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" :-)

Comment on lines -1085 to +1134
* 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 Author

Choose a reason for hiding this comment

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

I always use {} for statements that could be written on a single line - because if we ended up adding a new line there the change would be smaller and clearer. that said, I am totally fine with trading it in for consistency-via-clang-format.

Copy link
Member

Choose a reason for hiding this comment

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

that said, I am totally fine with trading it in for consistency-via-clang-format.

I'm really not. I don't think this is worth enforcing. It's a huge chunk of the lines getting changed.

@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.

Signed-off-by: Ping Xie <pingxie@google.com>
Signed-off-by: Ping Xie <pingxie@google.com>
Signed-off-by: Ping Xie <pingxie@google.com>
Signed-off-by: Ping Xie <pingxie@google.com>
@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 :-)

@@ -1239,12 +1340,14 @@
#define GETFAIR_NUM_ENTRIES 15
dictEntry *dictGetFairRandomKey(dict *d) {
dictEntry *entries[GETFAIR_NUM_ENTRIES];
unsigned int count = dictGetSomeKeys(d,entries,GETFAIR_NUM_ENTRIES);
unsigned int count = dictGetSomeKeys(d, entries, GETFAIR_NUM_ENTRIES);

Check failure

Code scanning / CodeQL

Use of a broken or risky cryptographic algorithm High

This file makes use of a broken or weak cryptographic algorithm (specified by
call to dictGetSomeKeys
).
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 a perfect example of why I don't want to allow a computer to have full control over ... my car ... my meals ... my code's format ... or much of anything. Yes, if it were being used for cryptography it would be bad, but that's not what it is being used for.

@@ -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 High

This file makes use of a broken or weak cryptographic algorithm (specified by
call to kvstoreDictGetSomeKeys
).
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 (ba9dd7b) to head (7d728c7).

Additional details and impacted files
@@             Coverage Diff              @@
##           unstable     #323      +/-   ##
============================================
- Coverage     68.95%   68.05%   -0.91%     
============================================
  Files           109      109              
  Lines         61793    63657    +1864     
============================================
+ Hits          42611    43321     +710     
- Misses        19182    20336    +1154     
Files Coverage Δ
src/acl.c 88.00% <ø> (-0.98%) ⬇️
src/asciilogo.h 100.00% <100.00%> (ø)
src/cluster_legacy.c 82.46% <ø> (-0.73%) ⬇️
src/config.c 77.03% <ø> (-0.52%) ⬇️
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

@@ -61,73 +61,79 @@
#define MM 156
#define MATRIX_A 0xB5026F5AA96619E9ULL
#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */
#define LM 0x7FFFFFFFULL /* Least significant 31 bits */
#define LM 0x7FFFFFFFULL /* Least significant 31 bits */
Copy link
Member

Choose a reason for hiding this comment

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

We should exclude the files that were copied instead of written for the project. This will just make future merges annoying. I think the list is mt19937-64.c/h, lfz_c, sha256, sha1, strl.c

Copy link
Contributor

Choose a reason for hiding this comment

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

And pqsort.c, crccombine.*, crcspeed.*

We can put them in a file called .clang-format-ignore

Copy link
Member

Choose a reason for hiding this comment

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

Or we can add the do-not-format annotation to the files, marking them from start to end. Then if we have to patch them, we can use multiple annotations so that we still autoformat our patches.

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 Show resolved Hide resolved
src/latency.c Show resolved Hide resolved
src/listpack.c Show resolved Hide resolved
src/listpack.c Show resolved Hide resolved
src/module.c Show resolved Hide resolved
src/object.c Show resolved Hide resolved
src/object.c Show resolved Hide resolved
src/object.c Show resolved Hide resolved
src/object.c Show resolved Hide resolved
src/object.c Show resolved Hide resolved
Comment on lines 226 to 227
} else if ((opt[0] == 'g' || opt[0] == 'G') &&
(opt[1] == 'e' || opt[1] == 'E') &&
(opt[2] == 't' || opt[2] == 'T') && opt[3] == '\0' &&
(command_type == COMMAND_SET))
{
} else if ((opt[0] == 'g' || opt[0] == 'G') && (opt[1] == 'e' || opt[1] == 'E') &&
(opt[2] == 't' || opt[2] == 'T') && opt[3] == '\0' && (command_type == COMMAND_SET)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

These are nice to read vertically as "get" vs "GET". I want to disable formatting for this function.

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 curious. Does this code really run that much faster than strcasecmp? If it does, can we refactor it into a macro or an inline or something so that it reads something like the following?

} else if (IS_GET(opt) && (command_type == COMMAND_SET))
        {

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know but i don't want to spend time on it now. Feel free to improve this if you want.

Copy link
Contributor

Choose a reason for hiding this comment

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

The conversion of a char to upper is just one bit flip, c & ~0x20.

@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>
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

6 participants