From: Ben Hamilton Date: Thu, 22 Mar 2018 17:37:19 +0000 (+0000) Subject: [clang-format] Fix ObjC style guesser to also iterate over child lines X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6ef13cd268d2e88861e5240f6feb943d5c51b229;p=clang [clang-format] Fix ObjC style guesser to also iterate over child lines Summary: When I wrote `ObjCHeaderStyleGuesser`, I incorrectly assumed the correct way to iterate over all tokens in `AnnotatedLine` was to iterate over the linked list tokens starting with `AnnotatedLine::First`. However, `AnnotatedLine` also contains a vector `AnnotedLine::Children` with child `AnnotedLine`s which have their own tokens which we need to iterate over. Because I didn't iterate over the tokens in the children lines, the ObjC style guesser would fail on syntax like: #define FOO ({ NSString *s = ... }) as the statement(s) inside { ... } are child lines. This fixes the bug and adds a test. I confirmed the test failed before the fix, and passed after the fix. Test Plan: New tests added. Ran tests with: % make -j12 FormatTests && ./tools/clang/unittests/Format/FormatTests Reviewers: djasper, jolesiak, Wizard Reviewed By: djasper Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D44790 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@328220 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index e9d1fafe86..ac22d6b450 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -1514,8 +1514,8 @@ private: "UIView", }; - for (auto &Line : AnnotatedLines) { - for (FormatToken *FormatTok = Line->First; FormatTok; + auto LineContainsObjCCode = [&Keywords](const AnnotatedLine &Line) { + for (const FormatToken *FormatTok = Line.First; FormatTok; FormatTok = FormatTok->Next) { if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && (FormatTok->isObjCAtKeyword(tok::objc_interface) || @@ -1536,6 +1536,15 @@ private: return true; } } + return false; + }; + for (auto Line : AnnotatedLines) { + if (LineContainsObjCCode(*Line)) + return true; + for (auto ChildLine : Line->Children) { + if (LineContainsObjCCode(*ChildLine)) + return true; + } } return false; } diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 6fb2903427..36ed318eec 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -12166,6 +12166,13 @@ TEST_F(FormatTest, GuessLanguageWithCaret) { guessLanguage("foo.h", "int(^foo[(kNumEntries + 10)])(char, float);")); } +TEST_F(FormatTest, GuessLanguageWithChildLines) { + EXPECT_EQ(FormatStyle::LK_Cpp, + guessLanguage("foo.h", "#define FOO ({ std::string s; })")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "#define FOO ({ NSString *s; })")); +} + } // end namespace } // end namespace format } // end namespace clang