Skip to content

Commit

Permalink
[clang-format] Do not break Objective-C string literals inside array …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
bhamiltoncx committed Feb 8, 2018
1 parent 976f317 commit 09051f2
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 1 deletion.
8 changes: 8 additions & 0 deletions clang/lib/Format/ContinuationIndenter.cpp
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/Format/ContinuationIndenter.h
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions clang/unittests/Format/FormatTestObjC.cpp
Expand Up @@ -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
Expand Down

0 comments on commit 09051f2

Please sign in to comment.