diff options
| author | Ben Hamilton <benhamilton@google.com> | 2018-02-08 16:07:25 +0000 |
|---|---|---|
| committer | Ben Hamilton <benhamilton@google.com> | 2018-02-08 16:07:25 +0000 |
| commit | 09051f2925ae059ac724ebd2b6de01aa239f26c6 (patch) | |
| tree | 759b2d94c9b9274cd0515411387f973c1081bad0 /clang | |
| parent | 976f317f0c89cab5d5e849b66993472486869ffd (diff) | |
| download | bcm5719-llvm-09051f2925ae059ac724ebd2b6de01aa239f26c6.tar.gz bcm5719-llvm-09051f2925ae059ac724ebd2b6de01aa239f26c6.zip | |
[clang-format] Do not break Objective-C string literals inside array literals
Summary:
Concatenating Objective-C string literals inside an array literal
raises the warning -Wobjc-string-concatenation (which is enabled by default).
clang-format currently splits and concatenates string literals like
the following:
NSArray *myArray = @[ @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ];
into:
NSArray *myArray =
@[ @"aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
@"aaaaaaaaa" ];
which raises the warning. This is https://bugs.llvm.org/show_bug.cgi?id=36153 .
The options I can think of to fix this are:
1) Have clang-format disable Wobjc-string-concatenation by emitting
pragmas around the formatted code
2) Have clang-format wrap the string literals in a macro (which
disables the warning)
3) Disable string splitting for Objective-C string literals inside
array literals
I think 1) has no precedent, and I couldn't find a good
identity() macro for 2). So, this diff implements 3).
Test Plan: make -j12 FormatTests && ./tools/clang/unittests/Format/FormatTests
Reviewers: jolesiak, stephanemoore, djasper
Reviewed By: jolesiak
Subscribers: klimek, cfe-commits
Differential Revision: https://reviews.llvm.org/D42704
llvm-svn: 324618
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Format/ContinuationIndenter.h | 7 | ||||
| -rw-r--r-- | clang/unittests/Format/FormatTestObjC.cpp | 6 |
3 files changed, 20 insertions, 1 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 6ee299566e4..14f8f05645d 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -1285,6 +1285,9 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, State.Stack.back().NestedBlockIndent = NestedBlockIndent; State.Stack.back().BreakBeforeParameter = BreakBeforeParameter; State.Stack.back().HasMultipleNestedBlocks = Current.BlockParameterCount > 1; + State.Stack.back().IsInsideObjCArrayLiteral = + Current.is(TT_ArrayInitializerLSquare) && Current.Previous && + Current.Previous->is(tok::at); } void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) { @@ -1578,6 +1581,11 @@ std::unique_ptr<BreakableToken> ContinuationIndenter::createBreakableToken( // likely want to terminate the string before any line breaking is done. if (Current.IsUnterminatedLiteral) return nullptr; + // Don't break string literals inside Objective-C array literals (doing so + // raises the warning -Wobjc-string-concatenation). + if (State.Stack.back().IsInsideObjCArrayLiteral) { + return nullptr; + } StringRef Text = Current.TokenText; StringRef Prefix; diff --git a/clang/lib/Format/ContinuationIndenter.h b/clang/lib/Format/ContinuationIndenter.h index bb2b7320fd4..64b3a3eba9f 100644 --- a/clang/lib/Format/ContinuationIndenter.h +++ b/clang/lib/Format/ContinuationIndenter.h @@ -208,7 +208,8 @@ struct ParenState { NoLineBreakInOperand(false), LastOperatorWrapped(true), ContainsLineBreak(false), ContainsUnwrappedBuilder(false), AlignColons(true), ObjCSelectorNameFound(false), - HasMultipleNestedBlocks(false), NestedBlockInlined(false) {} + HasMultipleNestedBlocks(false), NestedBlockInlined(false), + IsInsideObjCArrayLiteral(false) {} /// \brief The position to which a specific parenthesis level needs to be /// indented. @@ -318,6 +319,10 @@ struct ParenState { /// "function" in JavaScript) is not wrapped to a new line. bool NestedBlockInlined : 1; + /// \brief \c true if the current \c ParenState represents an Objective-C + /// array literal. + bool IsInsideObjCArrayLiteral : 1; + bool operator<(const ParenState &Other) const { if (Indent != Other.Indent) return Indent < Other.Indent; diff --git a/clang/unittests/Format/FormatTestObjC.cpp b/clang/unittests/Format/FormatTestObjC.cpp index d270aabea5b..df2e067a302 100644 --- a/clang/unittests/Format/FormatTestObjC.cpp +++ b/clang/unittests/Format/FormatTestObjC.cpp @@ -975,6 +975,12 @@ TEST_F(FormatTestObjC, ObjCArrayLiterals) { verifyFormat("[someFunction someLooooooooooooongParameter:@[\n" " NSBundle.mainBundle.infoDictionary[@\"a\"]\n" "]];"); + Style.ColumnLimit = 20; + // We can't break string literals inside NSArray literals + // (that raises -Wobjc-string-concatenation). + verifyFormat("NSArray *foo = @[\n" + " @\"aaaaaaaaaaaaaaaaaaaaaaaaaa\"\n" + "];\n"); } } // end namespace } // end namespace format |

