зеркало из https://github.com/microsoft/clang-1.git
Takes the context into account when re-indenting regions.
Fixes llvm.org/PR14916. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174720 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
bfaa111e71
Коммит
547d5db5ed
|
@ -921,34 +921,90 @@ public:
|
|||
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
|
||||
Annotator.calculateFormattingInformation(AnnotatedLines[i]);
|
||||
}
|
||||
std::vector<int> IndentForLevel;
|
||||
for (std::vector<AnnotatedLine>::iterator I = AnnotatedLines.begin(),
|
||||
E = AnnotatedLines.end();
|
||||
I != E; ++I) {
|
||||
const AnnotatedLine &TheLine = *I;
|
||||
int Offset = GetIndentOffset(TheLine.First);
|
||||
while (IndentForLevel.size() <= TheLine.Level)
|
||||
IndentForLevel.push_back(-1);
|
||||
IndentForLevel.resize(TheLine.Level + 1);
|
||||
if (touchesRanges(TheLine) && TheLine.Type != LT_Invalid) {
|
||||
unsigned Indent =
|
||||
formatFirstToken(TheLine.First, TheLine.Level,
|
||||
TheLine.InPPDirective, PreviousEndOfLineColumn);
|
||||
unsigned LevelIndent = GetIndent(IndentForLevel, TheLine.Level);
|
||||
unsigned Indent = LevelIndent;
|
||||
if (static_cast<int>(Indent) + Offset >= 0)
|
||||
Indent += Offset;
|
||||
if (!TheLine.First.FormatTok.WhiteSpaceStart.isValid() ||
|
||||
StructuralError) {
|
||||
Indent = LevelIndent = SourceMgr.getSpellingColumnNumber(
|
||||
TheLine.First.FormatTok.Tok.getLocation()) - 1;
|
||||
} else {
|
||||
formatFirstToken(TheLine.First, Indent, TheLine.InPPDirective,
|
||||
PreviousEndOfLineColumn);
|
||||
}
|
||||
tryFitMultipleLinesInOne(Indent, I, E);
|
||||
UnwrappedLineFormatter Formatter(Style, SourceMgr, TheLine, Indent,
|
||||
TheLine.First, Whitespaces,
|
||||
StructuralError);
|
||||
PreviousEndOfLineColumn = Formatter.format();
|
||||
IndentForLevel[TheLine.Level] = LevelIndent;
|
||||
} else {
|
||||
// If we did not reformat this unwrapped line, the column at the end of
|
||||
// the last token is unchanged - thus, we can calculate the end of the
|
||||
// last token, and return the result.
|
||||
// last token.
|
||||
PreviousEndOfLineColumn =
|
||||
SourceMgr.getSpellingColumnNumber(
|
||||
TheLine.Last->FormatTok.Tok.getLocation()) +
|
||||
Lex.MeasureTokenLength(TheLine.Last->FormatTok.Tok.getLocation(),
|
||||
SourceMgr, Lex.getLangOpts()) - 1;
|
||||
unsigned Indent = SourceMgr.getSpellingColumnNumber(
|
||||
TheLine.First.FormatTok.Tok.getLocation()) - 1;
|
||||
unsigned LevelIndent = Indent;
|
||||
if (static_cast<int>(LevelIndent) - Offset >= 0)
|
||||
LevelIndent -= Offset;
|
||||
IndentForLevel[TheLine.Level] = LevelIndent;
|
||||
}
|
||||
}
|
||||
return Whitespaces.generateReplacements();
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief Get the indent of \p Level from \p IndentForLevel.
|
||||
///
|
||||
/// \p IndentForLevel must contain the indent for the level \c l
|
||||
/// at \p IndentForLevel[l], or a value < 0 if the indent for
|
||||
/// that level is unknown.
|
||||
unsigned GetIndent(const std::vector<int> IndentForLevel,
|
||||
unsigned Level) {
|
||||
if (Level == 0)
|
||||
return 0;
|
||||
if (IndentForLevel[Level] != -1)
|
||||
return IndentForLevel[Level];
|
||||
return GetIndent(IndentForLevel, Level - 1) + 2;
|
||||
}
|
||||
|
||||
/// \brief Get the offset of the line relatively to the level.
|
||||
///
|
||||
/// For example, 'public:' labels in classes are offset by 1 or 2
|
||||
/// characters to the left from their level.
|
||||
int GetIndentOffset(const AnnotatedToken &RootToken) {
|
||||
bool IsAccessModifier = false;
|
||||
if (RootToken.is(tok::kw_public) || RootToken.is(tok::kw_protected) ||
|
||||
RootToken.is(tok::kw_private))
|
||||
IsAccessModifier = true;
|
||||
else if (RootToken.is(tok::at) && !RootToken.Children.empty() &&
|
||||
(RootToken.Children[0].isObjCAtKeyword(tok::objc_public) ||
|
||||
RootToken.Children[0].isObjCAtKeyword(tok::objc_protected) ||
|
||||
RootToken.Children[0].isObjCAtKeyword(tok::objc_package) ||
|
||||
RootToken.Children[0].isObjCAtKeyword(tok::objc_private)))
|
||||
IsAccessModifier = true;
|
||||
|
||||
if (IsAccessModifier)
|
||||
return Style.AccessModifierOffset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \brief Tries to merge lines into one.
|
||||
///
|
||||
/// This will change \c Line and \c AnnotatedLine to contain the merged line,
|
||||
|
@ -1109,40 +1165,21 @@ private:
|
|||
/// \brief Add a new line and the required indent before the first Token
|
||||
/// of the \c UnwrappedLine if there was no structural parsing error.
|
||||
/// Returns the indent level of the \c UnwrappedLine.
|
||||
unsigned formatFirstToken(const AnnotatedToken &RootToken, unsigned Level,
|
||||
bool InPPDirective,
|
||||
unsigned PreviousEndOfLineColumn) {
|
||||
void formatFirstToken(const AnnotatedToken &RootToken, unsigned Indent,
|
||||
bool InPPDirective, unsigned PreviousEndOfLineColumn) {
|
||||
const FormatToken &Tok = RootToken.FormatTok;
|
||||
if (!Tok.WhiteSpaceStart.isValid() || StructuralError)
|
||||
return SourceMgr.getSpellingColumnNumber(Tok.Tok.getLocation()) - 1;
|
||||
|
||||
unsigned Newlines =
|
||||
std::min(Tok.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
|
||||
if (Newlines == 0 && !Tok.IsFirst)
|
||||
Newlines = 1;
|
||||
unsigned Indent = Level * 2;
|
||||
|
||||
bool IsAccessModifier = false;
|
||||
if (RootToken.is(tok::kw_public) || RootToken.is(tok::kw_protected) ||
|
||||
RootToken.is(tok::kw_private))
|
||||
IsAccessModifier = true;
|
||||
else if (RootToken.is(tok::at) && !RootToken.Children.empty() &&
|
||||
(RootToken.Children[0].isObjCAtKeyword(tok::objc_public) ||
|
||||
RootToken.Children[0].isObjCAtKeyword(tok::objc_protected) ||
|
||||
RootToken.Children[0].isObjCAtKeyword(tok::objc_package) ||
|
||||
RootToken.Children[0].isObjCAtKeyword(tok::objc_private)))
|
||||
IsAccessModifier = true;
|
||||
|
||||
if (IsAccessModifier &&
|
||||
static_cast<int>(Indent) + Style.AccessModifierOffset >= 0)
|
||||
Indent += Style.AccessModifierOffset;
|
||||
if (!InPPDirective || Tok.HasUnescapedNewline) {
|
||||
Whitespaces.replaceWhitespace(RootToken, Newlines, Indent, 0, Style);
|
||||
} else {
|
||||
Whitespaces.replacePPWhitespace(RootToken, Newlines, Indent,
|
||||
PreviousEndOfLineColumn, Style);
|
||||
}
|
||||
return Indent;
|
||||
}
|
||||
|
||||
DiagnosticsEngine &Diag;
|
||||
|
|
|
@ -2544,5 +2544,56 @@ TEST_F(FormatTest, ObjCLiterals) {
|
|||
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, ReformatRegionAdjustsIndent) {
|
||||
EXPECT_EQ("{\n"
|
||||
"{\n"
|
||||
"a;\n"
|
||||
"b;\n"
|
||||
"}\n"
|
||||
"}", format("{\n"
|
||||
"{\n"
|
||||
"a;\n"
|
||||
" b;\n"
|
||||
"}\n"
|
||||
"}", 13, 2, getLLVMStyle()));
|
||||
EXPECT_EQ("{\n"
|
||||
"{\n"
|
||||
" a;\n"
|
||||
"b;\n"
|
||||
"}\n"
|
||||
"}", format("{\n"
|
||||
"{\n"
|
||||
" a;\n"
|
||||
"b;\n"
|
||||
"}\n"
|
||||
"}", 9, 2, getLLVMStyle()));
|
||||
EXPECT_EQ("{\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" b;\n"
|
||||
"}\n"
|
||||
"}", format("{\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" b;\n"
|
||||
"}\n"
|
||||
"}", 17, 2, getLLVMStyle()));
|
||||
EXPECT_EQ("{\n"
|
||||
"{\n"
|
||||
"a;\n"
|
||||
"}\n"
|
||||
"{\n"
|
||||
" b;\n"
|
||||
"}\n"
|
||||
"}", format("{\n"
|
||||
"{\n"
|
||||
"a;\n"
|
||||
"}\n"
|
||||
"{\n"
|
||||
" b;\n"
|
||||
"}\n"
|
||||
"}", 22, 2, getLLVMStyle()));
|
||||
}
|
||||
|
||||
} // end namespace tooling
|
||||
} // end namespace clang
|
||||
|
|
Загрузка…
Ссылка в новой задаче