summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancois Ferrand <thetypz@gmail.com>2018-02-09 15:41:56 +0000
committerFrancois Ferrand <thetypz@gmail.com>2018-02-09 15:41:56 +0000
commit38d801345880b8f3528f56af4f67ec4b0b79a577 (patch)
tree2e3b71667aea8d9d398477c23e3738c1518040d6
parent6f374a3d7588a41aa7509da86d6f3387c538fa47 (diff)
downloadbcm5719-llvm-38d801345880b8f3528f56af4f67ec4b0b79a577.tar.gz
bcm5719-llvm-38d801345880b8f3528f56af4f67ec4b0b79a577.zip
clang-format: keep ObjC colon alignment with short object name
Summary: When the target object expression is short and the first selector name is long, clang-format used to break the colon alignment: [I performSelectorOnMainThread:@selector(loadAccessories) withObject:nil waitUntilDone:false]; This happens because the colon is placed at `ContinuationIndent + LongestObjCSelectorName`, so that any selector can be wrapped. This is however not needed in case the longest selector is the firstone, and not wrapped. To overcome this, this patch does not include the first selector in `LongestObjCSelectorName` computation (in TokenAnnotator), and lets `ContinuationIndenter` decide how to account for the first selector when wrapping. (Note this was already partly the case, see line 521 of ContinuationIndenter.cpp) This way, the code gets properly aligned whenever possible without breaking the continuation indent. [I performSelectorOnMainThread:@selector(loadAccessories) withObject:nil waitUntilDone:false]; [I // force break performSelectorOnMainThread:@selector(loadAccessories) withObject:nil waitUntilDone:false]; [I perform:@selector(loadAccessories) withSelectorOnMainThread:true waitUntilDone:false]; Reviewers: krasimir, djasper, klimek Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D43121 llvm-svn: 324741
-rw-r--r--clang/lib/Format/ContinuationIndenter.cpp6
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp8
-rw-r--r--clang/unittests/Format/FormatTestObjC.cpp24
3 files changed, 30 insertions, 8 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 14f8f05645d..109dd1749ab 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -701,7 +701,8 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
? std::max(State.Stack.back().Indent,
State.FirstIndent + Style.ContinuationIndentWidth)
: State.Stack.back().Indent) +
- NextNonComment->LongestObjCSelectorName;
+ std::max(NextNonComment->LongestObjCSelectorName,
+ NextNonComment->ColumnWidth);
}
} else if (State.Stack.back().AlignColons &&
State.Stack.back().ColonPos <= NextNonComment->ColumnWidth) {
@@ -900,7 +901,8 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
? std::max(State.Stack.back().Indent,
State.FirstIndent + Style.ContinuationIndentWidth)
: State.Stack.back().Indent) +
- NextNonComment->LongestObjCSelectorName -
+ std::max(NextNonComment->LongestObjCSelectorName,
+ NextNonComment->ColumnWidth) -
NextNonComment->ColumnWidth;
}
if (!State.Stack.back().AlignColons)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index d8c3366941c..78c69d1e0fa 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -591,12 +591,12 @@ private:
BeforePrevious->is(tok::r_square) ||
Contexts.back().LongestObjCSelectorName == 0) {
Tok->Previous->Type = TT_SelectorName;
- if (Tok->Previous->ColumnWidth >
- Contexts.back().LongestObjCSelectorName)
- Contexts.back().LongestObjCSelectorName =
- Tok->Previous->ColumnWidth;
if (!Contexts.back().FirstObjCSelectorName)
Contexts.back().FirstObjCSelectorName = Tok->Previous;
+ else if (Tok->Previous->ColumnWidth >
+ Contexts.back().LongestObjCSelectorName)
+ Contexts.back().LongestObjCSelectorName =
+ Tok->Previous->ColumnWidth;
}
} else if (Contexts.back().ColonIsForRangeExpr) {
Tok->Type = TT_RangeBasedForLoopColon;
diff --git a/clang/unittests/Format/FormatTestObjC.cpp b/clang/unittests/Format/FormatTestObjC.cpp
index df2e067a302..a2cfb27eaff 100644
--- a/clang/unittests/Format/FormatTestObjC.cpp
+++ b/clang/unittests/Format/FormatTestObjC.cpp
@@ -693,8 +693,8 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) {
// Formats pair-parameters.
verifyFormat("[I drawRectOn:surface ofSize:aa:bbb atOrigin:cc:dd];");
verifyFormat("[I drawRectOn:surface //\n"
- " ofSize:aa:bbb\n"
- " atOrigin:cc:dd];");
+ " ofSize:aa:bbb\n"
+ " atOrigin:cc:dd];");
// Inline block as a first argument.
verifyFormat("[object justBlock:^{\n"
@@ -760,6 +760,26 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) {
" backing:NSBackingStoreBuffered\n"
" defer:NO]);\n"
"}");
+
+ // Respect continuation indent and colon alignment (e.g. when object name is
+ // short, and first selector is the longest one)
+ Style = getLLVMStyle();
+ Style.Language = FormatStyle::LK_ObjC;
+ Style.ContinuationIndentWidth = 8;
+ verifyFormat("[self performSelectorOnMainThread:@selector(loadAccessories)\n"
+ " withObject:nil\n"
+ " waitUntilDone:false];");
+ verifyFormat("[self performSelector:@selector(loadAccessories)\n"
+ " withObjectOnMainThread:nil\n"
+ " waitUntilDone:false];");
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " performSelectorOnMainThread:@selector(loadAccessories)\n"
+ " withObject:nil\n"
+ " waitUntilDone:false];");
+ verifyFormat("[self // force wrapping\n"
+ " performSelectorOnMainThread:@selector(loadAccessories)\n"
+ " withObject:nil\n"
+ " waitUntilDone:false];");
}
TEST_F(FormatTestObjC, ObjCAt) {
OpenPOWER on IntegriCloud