diff options
author | Daniel Jasper <djasper@google.com> | 2014-05-28 09:11:53 +0000 |
---|---|---|
committer | Daniel Jasper <djasper@google.com> | 2014-05-28 09:11:53 +0000 |
commit | 335ff26631b142d56b2954e37c51c2a979a34c53 (patch) | |
tree | a91bc5e2587ea14e23860f1561856f004a2ead14 /clang/lib | |
parent | 82ee0433da3c2d2f2eb9f46f80c463f71bb75c29 (diff) | |
download | bcm5719-llvm-335ff26631b142d56b2954e37c51c2a979a34c53.tar.gz bcm5719-llvm-335ff26631b142d56b2954e37c51c2a979a34c53.zip |
clang-format: Format array and dict literals similar to blocks.
Especially, reduce the amount of indentation if it doesn't increase
readability.
Before:
NSMutableDictionary* dictionary = [NSMutableDictionary
dictionaryWithDictionary:@{
aaaaaaaaaaaaaaaaaaaaa : aaaaaaaaaaaaa,
bbbbbbbbbbbbbbbbbb : bbbbb,
cccccccccccccccc : ccccccccccccccc
}];
After:
NSMutableDictionary* dictionary =
[NSMutableDictionary dictionaryWithDictionary:@{
aaaaaaaaaaaaaaaaaaaaa : aaaaaaaaaaaaa,
bbbbbbbbbbbbbbbbbb : bbbbb,
cccccccccccccccc : ccccccccccccccc
}];
llvm-svn: 209720
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 104 |
1 files changed, 59 insertions, 45 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 7485e0d40ae..01467f995d8 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -736,25 +736,58 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, } } +// Remove the fake r_parens after 'Tok'. +static void consumeRParens(LineState& State, const FormatToken &Tok) { + for (unsigned i = 0, e = Tok.FakeRParens; i != e; ++i) { + unsigned VariablePos = State.Stack.back().VariablePos; + assert(State.Stack.size() > 1); + if (State.Stack.size() == 1) { + // Do not pop the last element. + break; + } + State.Stack.pop_back(); + State.Stack.back().VariablePos = VariablePos; + } +} + +// Returns whether 'Tok' opens or closes a scope requiring special handling +// of the subsequent fake r_parens. +// +// For example, if this is an l_brace starting a nested block, we pretend (wrt. +// to indentation) that we already consumed the corresponding r_brace. Thus, we +// remove all ParenStates caused by fake parentheses that end at the r_brace. +// The net effect of this is that we don't indent relative to the l_brace, if +// the nested block is the last parameter of a function. This formats: +// +// SomeFunction(a, [] { +// f(); // break +// }); +// +// instead of: +// SomeFunction(a, [] { +// f(); // break +// }); +static bool fakeRParenSpecialCase(const FormatToken& Tok) { + if (!Tok.MatchingParen) + return false; + const FormatToken *Left = &Tok; + if (Tok.isOneOf(tok::r_brace, tok::r_square)) + Left = Tok.MatchingParen; + return Left->isOneOf(tok::l_brace, tok::l_square) && + (Left->BlockKind == BK_Block || + Left->Type == TT_ArrayInitializerLSquare || + Left->Type == TT_DictLiteral); +} + void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) { const FormatToken &Current = *State.NextToken; - // Remove scopes created by fake parenthesis. - if (Current.isNot(tok::r_brace) || - (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) { - // Don't remove FakeRParens attached to r_braces that surround nested blocks - // as they will have been removed early (see above). - for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) { - unsigned VariablePos = State.Stack.back().VariablePos; - assert(State.Stack.size() > 1); - if (State.Stack.size() == 1) { - // Do not pop the last element. - break; - } - State.Stack.pop_back(); - State.Stack.back().VariablePos = VariablePos; - } - } + // Don't remove FakeRParens attached to r_braces that surround nested blocks + // as they will have been removed early (see above). + if (fakeRParenSpecialCase(Current)) + return; + + consumeRParens(State, *State.NextToken); } void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, @@ -773,6 +806,9 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, bool AvoidBinPacking; bool BreakBeforeParameter = false; if (Current.is(tok::l_brace) || Current.Type == TT_ArrayInitializerLSquare) { + if (fakeRParenSpecialCase(Current)) + consumeRParens(State, *Current.MatchingParen); + NewIndent = State.Stack.back().LastSpace; if (Current.opensBlockTypeList(Style)) { NewIndent += Style.IndentWidth; @@ -824,9 +860,9 @@ void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) { if (State.Stack.size() > 1 && (Current.isOneOf(tok::r_paren, tok::r_square) || (Current.is(tok::r_brace) && State.NextToken != State.Line->First) || - State.NextToken->Type == TT_TemplateCloser)) { + State.NextToken->Type == TT_TemplateCloser)) State.Stack.pop_back(); - } + if (Current.is(tok::r_square)) { // If this ends the array subscript expr, reset the corresponding value. const FormatToken *NextNonComment = Current.getNextNonComment(); @@ -836,35 +872,13 @@ void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) { } void ContinuationIndenter::moveStateToNewBlock(LineState &State) { - // If this is an l_brace starting a nested block, we pretend (wrt. to - // indentation) that we already consumed the corresponding r_brace. Thus, we - // remove all ParenStates caused by fake parentheses that end at the r_brace. - // The net effect of this is that we don't indent relative to the l_brace, if - // the nested block is the last parameter of a function. For example, this - // formats: - // - // SomeFunction(a, [] { - // f(); // break - // }); - // - // instead of: - // SomeFunction(a, [] { - // f(); // break - // }); - // // If we have already found more than one lambda introducers on this level, we // opt out of this because similarity between the lambdas is more important. - if (State.Stack.back().LambdasFound <= 1) { - for (unsigned i = 0; i != State.NextToken->MatchingParen->FakeRParens; - ++i) { - assert(State.Stack.size() > 1); - if (State.Stack.size() == 1) { - // Do not pop the last element. - break; - } - State.Stack.pop_back(); - } - } + // FIXME: This should use fakeRParenSpecialCase() and fakeRParenSpecialCase() + // Needs to include the LambdasFound check. Otherwise the corresponding + // fake r_parens will never be consumed. + if (State.Stack.back().LambdasFound <= 1) + consumeRParens(State, *State.NextToken->MatchingParen); // For some reason, ObjC blocks are indented like continuations. unsigned NewIndent = State.Stack.back().LastSpace + |