From 6432afe50c4b3afc4beb99b9392e8a1967bd6838 Mon Sep 17 00:00:00 2001 From: Ben Hamilton Date: Thu, 22 Mar 2018 17:37:19 +0000 Subject: [PATCH] [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 llvm-svn: 328220 --- clang/lib/Format/Format.cpp | 13 +++++++++++-- clang/unittests/Format/FormatTest.cpp | 7 +++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index e9d1faf..ac22d6b 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/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/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 6fb2903..36ed318 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/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 -- 2.7.4