summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrasimir Georgiev <krasimir@google.com>2017-04-21 14:35:20 +0000
committerKrasimir Georgiev <krasimir@google.com>2017-04-21 14:35:20 +0000
commitf47413706b6ab9dfce6ae1df4e2e6ff849795832 (patch)
treea422946060c87144194b7be6d4a51dfeff9a2a5b
parent9152c27ed99dbb24dbea073f57863ead7e98643d (diff)
[clang-format] Replace IncompleteFormat by a struct with Line
Summary: This patch replaces the boolean IncompleteFormat that is used to notify the client if an unrecoverable syntax error occurred by a struct that also contains a line number. Reviewers: djasper Reviewed By: djasper Subscribers: cfe-commits, klimek Differential Revision: https://reviews.llvm.org/D32298 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300985 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Format/Format.h27
-rw-r--r--lib/Format/Format.cpp27
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp7
-rw-r--r--lib/Format/UnwrappedLineFormatter.h9
-rw-r--r--test/Format/incomplete.cpp2
-rw-r--r--tools/clang-format/ClangFormat.cpp17
-rw-r--r--unittests/Format/FormatTest.cpp27
-rw-r--r--unittests/Format/FormatTestComments.cpp23
-rw-r--r--unittests/Format/FormatTestJS.cpp6
-rw-r--r--unittests/Format/FormatTestObjC.cpp23
-rw-r--r--unittests/Format/FormatTestSelective.cpp6
11 files changed, 110 insertions, 64 deletions
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 05daf4f897..9bed253bac 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -1512,6 +1512,18 @@ llvm::Expected<tooling::Replacements>
cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
const FormatStyle &Style);
+/// \brief Represents the status of a formatting attempt.
+struct FormattingAttemptStatus {
+ /// \brief A value of ``false`` means that any of the affected ranges were not
+ /// formatted due to a non-recoverable syntax error.
+ bool FormatComplete = true;
+
+ /// \brief If ``FormatComplete`` is false, ``Line`` records a one-based
+ /// original line number at which a syntax error might have occurred. This is
+ /// based on a best-effort analysis and could be imprecise.
+ unsigned Line = 0;
+};
+
/// \brief Reformats the given \p Ranges in \p Code.
///
/// Each range is extended on either end to its next bigger logic unit, i.e.
@@ -1521,13 +1533,20 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
/// Returns the ``Replacements`` necessary to make all \p Ranges comply with
/// \p Style.
///
-/// If ``IncompleteFormat`` is non-null, its value will be set to true if any
-/// of the affected ranges were not formatted due to a non-recoverable syntax
-/// error.
+/// If ``Status`` is non-null, its value will be populated with the status of
+/// this formatting attempt. See \c FormattingAttemptStatus.
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName = "<stdin>",
- bool *IncompleteFormat = nullptr);
+ FormattingAttemptStatus *Status = nullptr);
+
+/// \brief Same as above, except if ``IncompleteFormat`` is non-null, its value
+/// will be set to true if any of the affected ranges were not formatted due to
+/// a non-recoverable syntax error.
+tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges,
+ StringRef FileName,
+ bool *IncompleteFormat);
/// \brief Clean up any erroneous/redundant code in the given \p Ranges in \p
/// Code.
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 0e2da71343..f55a623a8d 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -908,8 +908,8 @@ private:
class Formatter : public TokenAnalyzer {
public:
Formatter(const Environment &Env, const FormatStyle &Style,
- bool *IncompleteFormat)
- : TokenAnalyzer(Env, Style), IncompleteFormat(IncompleteFormat) {}
+ FormattingAttemptStatus *Status)
+ : TokenAnalyzer(Env, Style), Status(Status) {}
tooling::Replacements
analyze(TokenAnnotator &Annotator,
@@ -931,7 +931,7 @@ public:
Env.getSourceManager(), Whitespaces, Encoding,
BinPackInconclusiveFunctions);
UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(),
- IncompleteFormat)
+ Env.getSourceManager(), Status)
.format(AnnotatedLines);
for (const auto &R : Whitespaces.generateReplacements())
if (Result.add(R))
@@ -1013,7 +1013,7 @@ private:
}
bool BinPackInconclusiveFunctions;
- bool *IncompleteFormat;
+ FormattingAttemptStatus *Status;
};
// This class clean up the erroneous/redundant code around the given ranges in
@@ -1830,7 +1830,8 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
- StringRef FileName, bool *IncompleteFormat) {
+ StringRef FileName,
+ FormattingAttemptStatus *Status) {
FormatStyle Expanded = expandPresets(Style);
if (Expanded.DisableFormat)
return tooling::Replacements();
@@ -1846,11 +1847,11 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
auto NewEnv = Environment::CreateVirtualEnvironment(
*NewCode, FileName,
tooling::calculateRangesAfterReplacements(Fixes, Ranges));
- Formatter Format(*NewEnv, Expanded, IncompleteFormat);
+ Formatter Format(*NewEnv, Expanded, Status);
return Fixes.merge(Format.process());
}
}
- Formatter Format(*Env, Expanded, IncompleteFormat);
+ Formatter Format(*Env, Expanded, Status);
return Format.process();
};
@@ -1866,7 +1867,7 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
return reformatAfterApplying(Requoter);
}
- Formatter Format(*Env, Expanded, IncompleteFormat);
+ Formatter Format(*Env, Expanded, Status);
return Format.process();
}
@@ -1879,6 +1880,16 @@ tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
return Clean.process();
}
+tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges,
+ StringRef FileName, bool *IncompleteFormat) {
+ FormattingAttemptStatus Status;
+ auto Result = reformat(Style, Code, Ranges, FileName, &Status);
+ if (!Status.FormatComplete)
+ *IncompleteFormat = true;
+ return Result;
+}
+
tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
StringRef Code,
ArrayRef<tooling::Range> Ranges,
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index c3c154afeb..8ff893426e 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -835,8 +835,11 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
bool ShouldFormat = TheLine.Affected || FixIndentation;
// We cannot format this line; if the reason is that the line had a
// parsing error, remember that.
- if (ShouldFormat && TheLine.Type == LT_Invalid && IncompleteFormat)
- *IncompleteFormat = true;
+ if (ShouldFormat && TheLine.Type == LT_Invalid && Status) {
+ Status->FormatComplete = false;
+ Status->Line =
+ SourceMgr.getSpellingLineNumber(TheLine.First->Tok.getLocation());
+ }
if (ShouldFormat && TheLine.Type != LT_Invalid) {
if (!DryRun)
diff --git a/lib/Format/UnwrappedLineFormatter.h b/lib/Format/UnwrappedLineFormatter.h
index 93247f71d6..55f0d1cac6 100644
--- a/lib/Format/UnwrappedLineFormatter.h
+++ b/lib/Format/UnwrappedLineFormatter.h
@@ -32,9 +32,11 @@ public:
WhitespaceManager *Whitespaces,
const FormatStyle &Style,
const AdditionalKeywords &Keywords,
- bool *IncompleteFormat)
+ const SourceManager &SourceMgr,
+ FormattingAttemptStatus *Status)
: Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
- Keywords(Keywords), IncompleteFormat(IncompleteFormat) {}
+ Keywords(Keywords), SourceMgr(SourceMgr),
+ Status(Status) {}
/// \brief Format the current block and return the penalty.
unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines,
@@ -63,7 +65,8 @@ private:
WhitespaceManager *Whitespaces;
const FormatStyle &Style;
const AdditionalKeywords &Keywords;
- bool *IncompleteFormat;
+ const SourceManager &SourceMgr;
+ FormattingAttemptStatus *Status;
};
} // end namespace format
} // end namespace clang
diff --git a/test/Format/incomplete.cpp b/test/Format/incomplete.cpp
index 8a65fad657..f92d576193 100644
--- a/test/Format/incomplete.cpp
+++ b/test/Format/incomplete.cpp
@@ -1,6 +1,6 @@
// RUN: grep -Ev "// *[A-Z-]+:" %s | clang-format -style=LLVM -cursor=0 \
// RUN: | FileCheck -strict-whitespace %s
-// CHECK: {{"IncompleteFormat": true}}
+// CHECK: {{"IncompleteFormat": true, "Line": 2}}
// CHECK: {{^int\ \i;$}}
int i;
// CHECK: {{^f \( g \(;$}}
diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp
index ac0d0a8512..14bff19a1a 100644
--- a/tools/clang-format/ClangFormat.cpp
+++ b/tools/clang-format/ClangFormat.cpp
@@ -276,14 +276,17 @@ static bool format(StringRef FileName) {
}
// Get new affected ranges after sorting `#includes`.
Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
- bool IncompleteFormat = false;
+ FormattingAttemptStatus Status;
Replacements FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges,
- AssumedFileName, &IncompleteFormat);
+ AssumedFileName, &Status);
Replaces = Replaces.merge(FormatChanges);
if (OutputXML) {
outs() << "<?xml version='1.0'?>\n<replacements "
"xml:space='preserve' incomplete_format='"
- << (IncompleteFormat ? "true" : "false") << "'>\n";
+ << (Status.FormatComplete ? "false" : "true") << "'";
+ if (!Status.FormatComplete)
+ outs() << " line=" << Status.Line;
+ outs() << ">\n";
if (Cursor.getNumOccurrences() != 0)
outs() << "<cursor>"
<< FormatChanges.getShiftedCodePosition(CursorPosition)
@@ -307,11 +310,15 @@ static bool format(StringRef FileName) {
if (Rewrite.overwriteChangedFiles())
return true;
} else {
- if (Cursor.getNumOccurrences() != 0)
+ if (Cursor.getNumOccurrences() != 0) {
outs() << "{ \"Cursor\": "
<< FormatChanges.getShiftedCodePosition(CursorPosition)
<< ", \"IncompleteFormat\": "
- << (IncompleteFormat ? "true" : "false") << " }\n";
+ << (Status.FormatComplete ? "false" : "true");
+ if (!Status.FormatComplete)
+ outs() << ", \"Line\": " << Status.Line;
+ outs() << " }\n";
+ }
Rewrite.getEditBuffer(ID).write(outs());
}
}
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index e6ba2230ac..7d5b77bffd 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -30,24 +30,25 @@ FormatStyle getGoogleStyle() { return getGoogleStyle(FormatStyle::LK_Cpp); }
class FormatTest : public ::testing::Test {
protected:
- enum IncompleteCheck {
- IC_ExpectComplete,
- IC_ExpectIncomplete,
- IC_DoNotCheck
+ enum StatusCheck {
+ SC_ExpectComplete,
+ SC_ExpectIncomplete,
+ SC_DoNotCheck
};
std::string format(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle(),
- IncompleteCheck CheckIncomplete = IC_ExpectComplete) {
+ StatusCheck CheckComplete = SC_ExpectComplete) {
DEBUG(llvm::errs() << "---\n");
DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
- bool IncompleteFormat = false;
+ FormattingAttemptStatus Status;
tooling::Replacements Replaces =
- reformat(Style, Code, Ranges, "<stdin>", &IncompleteFormat);
- if (CheckIncomplete != IC_DoNotCheck) {
- bool ExpectedIncompleteFormat = CheckIncomplete == IC_ExpectIncomplete;
- EXPECT_EQ(ExpectedIncompleteFormat, IncompleteFormat) << Code << "\n\n";
+ reformat(Style, Code, Ranges, "<stdin>", &Status);
+ if (CheckComplete != SC_DoNotCheck) {
+ bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
+ EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
+ << Code << "\n\n";
}
ReplacementCount = Replaces.size();
auto Result = applyAllReplacements(Code, Replaces);
@@ -83,7 +84,7 @@ protected:
void verifyIncompleteFormat(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
EXPECT_EQ(Code.str(),
- format(test::messUp(Code), Style, IC_ExpectIncomplete));
+ format(test::messUp(Code), Style, SC_ExpectIncomplete));
}
void verifyGoogleFormat(llvm::StringRef Code) {
@@ -98,7 +99,7 @@ protected:
/// \brief Verify that clang-format does not crash on the given input.
void verifyNoCrash(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
- format(Code, Style, IC_DoNotCheck);
+ format(Code, Style, SC_DoNotCheck);
}
int ReplacementCount;
@@ -6189,7 +6190,7 @@ TEST_F(FormatTest, SkipsDeeplyNestedLines) {
// Deeply nested part is untouched, rest is formatted.
EXPECT_EQ(std::string("int i;\n") + Code + "int j;\n",
format(std::string("int i;\n") + Code + "int j;\n",
- getLLVMStyle(), IC_ExpectIncomplete));
+ getLLVMStyle(), SC_ExpectIncomplete));
}
//===----------------------------------------------------------------------===//
diff --git a/unittests/Format/FormatTestComments.cpp b/unittests/Format/FormatTestComments.cpp
index e6310158e9..4238efe54f 100644
--- a/unittests/Format/FormatTestComments.cpp
+++ b/unittests/Format/FormatTestComments.cpp
@@ -29,24 +29,25 @@ FormatStyle getGoogleStyle() { return getGoogleStyle(FormatStyle::LK_Cpp); }
class FormatTestComments : public ::testing::Test {
protected:
- enum IncompleteCheck {
- IC_ExpectComplete,
- IC_ExpectIncomplete,
- IC_DoNotCheck
+ enum StatusCheck {
+ SC_ExpectComplete,
+ SC_ExpectIncomplete,
+ SC_DoNotCheck
};
std::string format(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle(),
- IncompleteCheck CheckIncomplete = IC_ExpectComplete) {
+ StatusCheck CheckComplete = SC_ExpectComplete) {
DEBUG(llvm::errs() << "---\n");
DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
- bool IncompleteFormat = false;
+ FormattingAttemptStatus Status;
tooling::Replacements Replaces =
- reformat(Style, Code, Ranges, "<stdin>", &IncompleteFormat);
- if (CheckIncomplete != IC_DoNotCheck) {
- bool ExpectedIncompleteFormat = CheckIncomplete == IC_ExpectIncomplete;
- EXPECT_EQ(ExpectedIncompleteFormat, IncompleteFormat) << Code << "\n\n";
+ reformat(Style, Code, Ranges, "<stdin>", &Status);
+ if (CheckComplete != SC_DoNotCheck) {
+ bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
+ EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
+ << Code << "\n\n";
}
ReplacementCount = Replaces.size();
auto Result = applyAllReplacements(Code, Replaces);
@@ -73,7 +74,7 @@ protected:
/// \brief Verify that clang-format does not crash on the given input.
void verifyNoCrash(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
- format(Code, Style, IC_DoNotCheck);
+ format(Code, Style, SC_DoNotCheck);
}
int ReplacementCount;
diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp
index d8fa8e4b94..c3c3e3aafb 100644
--- a/unittests/Format/FormatTestJS.cpp
+++ b/unittests/Format/FormatTestJS.cpp
@@ -24,10 +24,10 @@ protected:
DEBUG(llvm::errs() << "---\n");
DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
- bool IncompleteFormat = false;
+ FormattingAttemptStatus Status;
tooling::Replacements Replaces =
- reformat(Style, Code, Ranges, "<stdin>", &IncompleteFormat);
- EXPECT_FALSE(IncompleteFormat);
+ reformat(Style, Code, Ranges, "<stdin>", &Status);
+ EXPECT_TRUE(Status.FormatComplete);
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp
index 680ff92f75..d2dc8bca00 100644
--- a/unittests/Format/FormatTestObjC.cpp
+++ b/unittests/Format/FormatTestObjC.cpp
@@ -33,23 +33,24 @@ protected:
Style.Language = FormatStyle::LK_ObjC;
}
- enum IncompleteCheck {
- IC_ExpectComplete,
- IC_ExpectIncomplete,
- IC_DoNotCheck
+ enum StatusCheck {
+ SC_ExpectComplete,
+ SC_ExpectIncomplete,
+ SC_DoNotCheck
};
std::string format(llvm::StringRef Code,
- IncompleteCheck CheckIncomplete = IC_ExpectComplete) {
+ StatusCheck CheckComplete = SC_ExpectComplete) {
DEBUG(llvm::errs() << "---\n");
DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
- bool IncompleteFormat = false;
+ FormattingAttemptStatus Status;
tooling::Replacements Replaces =
- reformat(Style, Code, Ranges, "<stdin>", &IncompleteFormat);
- if (CheckIncomplete != IC_DoNotCheck) {
- bool ExpectedIncompleteFormat = CheckIncomplete == IC_ExpectIncomplete;
- EXPECT_EQ(ExpectedIncompleteFormat, IncompleteFormat) << Code << "\n\n";
+ reformat(Style, Code, Ranges, "<stdin>", &Status);
+ if (CheckComplete != SC_DoNotCheck) {
+ bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
+ EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
+ << Code << "\n\n";
}
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
@@ -62,7 +63,7 @@ protected:
}
void verifyIncompleteFormat(StringRef Code) {
- EXPECT_EQ(Code.str(), format(test::messUp(Code), IC_ExpectIncomplete));
+ EXPECT_EQ(Code.str(), format(test::messUp(Code), SC_ExpectIncomplete));
}
FormatStyle Style;
diff --git a/unittests/Format/FormatTestSelective.cpp b/unittests/Format/FormatTestSelective.cpp
index 367dbafcaf..8046d7fab2 100644
--- a/unittests/Format/FormatTestSelective.cpp
+++ b/unittests/Format/FormatTestSelective.cpp
@@ -24,10 +24,10 @@ protected:
DEBUG(llvm::errs() << "---\n");
DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
- bool IncompleteFormat = false;
+ FormattingAttemptStatus Status;
tooling::Replacements Replaces =
- reformat(Style, Code, Ranges, "<stdin>", &IncompleteFormat);
- EXPECT_FALSE(IncompleteFormat) << Code << "\n\n";
+ reformat(Style, Code, Ranges, "<stdin>", &Status);
+ EXPECT_TRUE(Status.FormatComplete) << Code << "\n\n";
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
DEBUG(llvm::errs() << "\n" << *Result << "\n\n");