Fixes https://github.com/llvm/llvm-project/issues/52976.
- Make no formatting for macros
- Attach comment with definition headers
- Make no change on use of empty lines at block start/end
- Fix misrecognition of keyword namespace
Differential D116663
[clang-format] Fix SeparateDefinitionBlocks issues ksyx on Jan 5 2022, 7:29 AM. Authored by
Details Fixes https://github.com/llvm/llvm-project/issues/52976.
Diff Detail
Unit Tests
Event Timeline
Comment Actions } #if 0 <--- extra unwanted newline void func() { } <--- extra unwanted newline #endif void bar() { } Comment Actions namespace { <--- extraneous newline will be removed (just checking if thats what we want?) shouldn't it honour MaxEmptyLines? /* foo */ void foo() { } <--- extraneous newline will be removed (just checking if thats what we want?) shouldn't it honour MaxEmptyLines? } Comment Actions } #if 0 <--- extra unwanted newline void func() { } <--- extra unwanted newline #else <--- extra unwanted newline void bar() { } <--- extra unwanted newline #endif void bar() { } Comment Actions I highly recommend you running this on a large code base...I'm pulling this patch down and running it on my work code base, (because I want to use this feature). Don't take my highlighting issues as anything other than "Go faster I like it... ;-)" But this is an definitely and improvement, and this is a great feature (one I've been doing by hand for years, so I'm super excited.)
Comment Actions I did not come out with an implementation of this currently, but one alternative solution might be to make it leave the line spacing as original code?
Comment Actions Do we have any ifdef tests?
Comment Actions Its definitely a lot better (LGTM), as the original changes have been committed I might suggest we land these changes to get us much closer. (and reduce the churn and comments on this review) Whilst I think you have fixed https://github.com/llvm/llvm-project/issues/52976 This shows some other failure scenarios https://github.com/llvm/llvm-project/issues/45895 I kind of think those other failures might be better handled in other reviews? what do others think? Comment Actions Some nits only, otherwise no other comments from my part. +1
+1 When handling those, please split into separate issues.
Comment Actions If I am correct, the only one unfixed in this issue would be this improvement:
Comment Actions Not reproduced with the following code and command line: int foo(int x, int y) { int r = x*y; return r; } void bar() { } bin/clang-format test.cpp -style='{AlwaysBreakAfterReturnType: All, SeparateDefinitionBlocks: Always, BreakBeforeBraces: Allman}' But using HRESULT return type reproduced this, with -debug option it shows it as an identifier while this is not for primitive types like void. Comment Actions Seem related to the number of characters used in the type? void foo() {} LRES Foo::func() {} LRESU Foo::func() {} Comment Actions ---- AnnotatedTokens(L=0): M=0 C=0 T=Unknown S=1 F=0 B=0 BK=0 P=0 Name=identifier L=4 PPK=2 FakeLParens= FakeRParens=0 II=0x1592cb8 Text='LRES' M=1 C=1 T=FunctionDeclarationName S=1 F=0 B=0 BK=0 P=80 Name=identifier L=84 PPK=2 FakeLParens= FakeRParens=0 II=0x1592cf0 Text='barbabararr' M=0 C=0 T=Unknown S=0 F=0 B=0 BK=0 P=23 Name=l_paren L=85 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text='(' M=0 C=0 T=Unknown S=0 F=0 B=0 BK=0 P=140 Name=r_paren L=86 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=')' ---- ============================ ---- AnnotatedTokens(L=0): M=0 C=0 T=Unknown S=1 F=0 B=0 BK=0 P=0 Name=identifier L=5 PPK=2 FakeLParens= FakeRParens=0 II=0x2e8dcb8 Text='LRESU' ---- AnnotatedTokens(L=0): M=0 C=0 T=Unknown S=1 F=0 B=0 BK=0 P=0 Name=identifier L=11 PPK=2 FakeLParens= FakeRParens=0 II=0x2e8dcf0 Text='barbabararr' M=0 C=0 T=Unknown S=0 F=0 B=0 BK=0 P=23 Name=l_paren L=12 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text='(' M=0 C=0 T=Unknown S=0 F=0 B=0 BK=0 P=140 Name=r_paren L=13 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=')' ---- ============================ ---- AnnotatedTokens(L=0): M=0 C=0 T=Unknown S=1 F=0 B=0 BK=0 P=0 Name=void L=4 PPK=2 FakeLParens= FakeRParens=0 II=0x15a0618 Text='void' M=1 C=1 T=FunctionDeclarationName S=1 F=0 B=0 BK=0 P=80 Name=identifier L=84 PPK=2 FakeLParens= FakeRParens=0 II=0x15a9cc0 Text='barbabararr' M=0 C=0 T=Unknown S=0 F=0 B=0 BK=0 P=23 Name=l_paren L=85 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text='(' M=0 C=0 T=Unknown S=0 F=0 B=0 BK=0 P=140 Name=r_paren L=86 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=')' ---- What I observed from the debug output is that it has been split into two blocks for long type name in AnnotatedToken info, while the shorter one only have one block. Comment Actions .... if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) && tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) { addUnwrappedLine(); return; } Comment Actions https://github.com/llvm/llvm-project/commit/680b09ba8825311dc0fad69ed166a21e3f83bcbe Seems like this is intent for dealing with macro but somehow went into return type Comment Actions Without the SeparateDefinitionBlocks: Always the issue doesn't occur, this is unclear to me why double Func() {} LRES Foo::func() {} LRESU Foo::func() {} Comment Actions I think that perhaps if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) Passes.emplace_back([&](const Environment &Env) { return DefinitionBlockSeparator(Env, Expanded).process(); }); Should be moved to After the Formatter pass, thoughts? Comment Actions It does not seem to be working. The problem could be that when I am asking about Line->MightBeFunctionDecl && Line->mightBeFunctionDefinition(), it will just return false when it is a single annotated line like LRESULT and return true for the line foo() following, so the program adds a new line above this "true function definition line". However, those like LRES foo() { would surely be treated as a normal definition line. Comment Actions How about checking the line before in "LikelyDefinition", I may not sure I totally understand your logic... but if (PreviousLine && !PreviousLine->endsWith(tok::semi) && PreviousLine->startsWith(tok::identifier)) return false; So something like this auto LikelyDefinition = [this](const AnnotatedLine *Line, const AnnotatedLine *PreviousLine) { if (PreviousLine && !PreviousLine->endsWith(tok::semi) && PreviousLine->startsWith(tok::identifier)) return false; if ((Line->MightBeFunctionDecl && Line->mightBeFunctionDefinition()) || Line->startsWithNamespace()) return true; FormatToken *CurrentToken = Line->First; while (CurrentToken) { if (CurrentToken->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_enum) || (Style.isJavaScript() && CurrentToken->TokenText == "function")) return true; CurrentToken = CurrentToken->Next; } return false; }; This fixed this capitialized return type > 5 chars (which for people using clang-format to format windows code with DWORD,DWORD_PTR,DOUBLE,HRESULT,LRESULT this would be pretty bad. Comment Actions I see your point, but I think the problem is more likely to be coming from the token annotator that detected it as a macro and just start a new line? https://github.com/llvm/llvm-project/commit/680b09ba8825311dc0fad69ed166a21e3f83bcbe Comment Actions Hi, just to confirm, are there anything needed to be improved for this patch or it is ready to be committed? Thanks
|
Style.isJavaScript()