[cfe-commits] r169286 - in /cfe/trunk: lib/Format/Format.cpp lib/Format/UnwrappedLineParser.cpp lib/Format/UnwrappedLineParser.h unittests/Format/FormatTest.cpp

Alexander Kornienko alexfh at google.com
Tue Dec 4 09:27:51 PST 2012


Author: alexfh
Date: Tue Dec  4 11:27:50 2012
New Revision: 169286

URL: http://llvm.org/viewvc/llvm-project?rev=169286&view=rev
Log:
Error recovery part 2

Summary: Adds recovery for structural errors in clang-format.

Reviewers: djasper

Reviewed By: djasper

CC: cfe-commits, silvas

Differential Revision: http://llvm-reviews.chandlerc.com/D164

Modified:
    cfe/trunk/lib/Format/Format.cpp
    cfe/trunk/lib/Format/UnwrappedLineParser.cpp
    cfe/trunk/lib/Format/UnwrappedLineParser.h
    cfe/trunk/unittests/Format/FormatTest.cpp

Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=169286&r1=169285&r2=169286&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Tue Dec  4 11:27:50 2012
@@ -72,28 +72,29 @@
   UnwrappedLineFormatter(const FormatStyle &Style, SourceManager &SourceMgr,
                          const UnwrappedLine &Line,
                          const std::vector<TokenAnnotation> &Annotations,
-                         tooling::Replacements &Replaces)
+                         tooling::Replacements &Replaces, bool StructuralError)
       : Style(Style),
         SourceMgr(SourceMgr),
         Line(Line),
         Annotations(Annotations),
-        Replaces(Replaces) {
+        Replaces(Replaces),
+        StructuralError(StructuralError) {
     Parameters.PenaltyExtraLine = 100;
     Parameters.PenaltyIndentLevel = 5;
   }
 
   void format() {
-    formatFirstToken();
+    unsigned Indent = formatFirstToken();
     count = 0;
     IndentState State;
-    State.Column = Line.Level * 2 + Line.Tokens[0].Tok.getLength();
+    State.Column = Indent + Line.Tokens[0].Tok.getLength();
     State.CtorInitializerOnNewLine = false;
     State.InCtorInitializer = false;
     State.ConsumedTokens = 1;
 
     //State.UsedIndent.push_back(Line.Level * 2);
-    State.Indent.push_back(Line.Level * 2 + 4);
-    State.LastSpace.push_back(Line.Level * 2);
+    State.Indent.push_back(Indent + 4);
+    State.LastSpace.push_back(Indent);
 
     // Start iterating at 1 as we have correctly formatted of Token #0 above.
     for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
@@ -315,20 +316,22 @@
 
   /// \brief Add a new line and the required indent before the first Token
   /// of the \c UnwrappedLine.
-  void formatFirstToken() {
+  unsigned formatFirstToken() {
     const FormatToken &Token = Line.Tokens[0];
-    if (Token.WhiteSpaceStart.isValid()) {
-      unsigned Newlines =
-          std::min(Token.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
-      unsigned Offset = SourceMgr.getFileOffset(Token.WhiteSpaceStart);
-      if (Newlines == 0 && Offset != 0)
-        Newlines = 1;
-      unsigned Indent = Line.Level * 2;
-      if (Token.Tok.is(tok::kw_public) || Token.Tok.is(tok::kw_protected) ||
-          Token.Tok.is(tok::kw_private))
-        Indent += Style.AccessModifierOffset;
-      replaceWhitespace(Token, Newlines, Indent);
-    }
+    if (!Token.WhiteSpaceStart.isValid() || StructuralError)
+      return SourceMgr.getSpellingColumnNumber(Token.Tok.getLocation()) - 1;
+
+    unsigned Newlines =
+        std::min(Token.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
+    unsigned Offset = SourceMgr.getFileOffset(Token.WhiteSpaceStart);
+    if (Newlines == 0 && Offset != 0)
+      Newlines = 1;
+    unsigned Indent = Line.Level * 2;
+    if (Token.Tok.is(tok::kw_public) || Token.Tok.is(tok::kw_protected) ||
+        Token.Tok.is(tok::kw_private))
+      Indent += Style.AccessModifierOffset;
+    replaceWhitespace(Token, Newlines, Indent);
+    return Indent;
   }
 
   FormatStyle Style;
@@ -337,6 +340,7 @@
   const std::vector<TokenAnnotation> &Annotations;
   tooling::Replacements &Replaces;
   unsigned int count;
+  bool StructuralError;
 
   OptimizationParameters Parameters;
 };
@@ -678,17 +682,26 @@
       : Style(Style),
         Lex(Lex),
         SourceMgr(SourceMgr),
-        Ranges(Ranges) {
+        Ranges(Ranges),
+        StructuralError(false) {
   }
 
   tooling::Replacements format() {
     UnwrappedLineParser Parser(Lex, SourceMgr, *this);
-    Parser.parse();
+    StructuralError = Parser.parse();
+    for (std::vector<UnwrappedLine>::iterator I = UnwrappedLines.begin(),
+                                              E = UnwrappedLines.end();
+         I != E; ++I)
+      doFormatUnwrappedLine(*I);
     return Replaces;
   }
 
 private:
   virtual void formatUnwrappedLine(const UnwrappedLine &TheLine) {
+    UnwrappedLines.push_back(TheLine);
+  }
+
+  void doFormatUnwrappedLine(const UnwrappedLine &TheLine) {
     if (TheLine.Tokens.size() == 0)
       return;
 
@@ -706,7 +719,8 @@
       TokenAnnotator Annotator(TheLine, Style, SourceMgr);
       Annotator.annotate();
       UnwrappedLineFormatter Formatter(Style, SourceMgr, TheLine,
-                                       Annotator.getAnnotations(), Replaces);
+                                       Annotator.getAnnotations(), Replaces,
+                                       StructuralError);
       Formatter.format();
       return;
     }
@@ -717,6 +731,8 @@
   SourceManager &SourceMgr;
   tooling::Replacements Replaces;
   std::vector<CharSourceRange> Ranges;
+  std::vector<UnwrappedLine> UnwrappedLines;
+  bool StructuralError;
 };
 
 tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=169286&r1=169285&r2=169286&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Tue Dec  4 11:27:50 2012
@@ -32,12 +32,13 @@
   Lex.SetKeepWhitespaceMode(true);
 }
 
-void UnwrappedLineParser::parse() {
+bool UnwrappedLineParser::parse() {
   parseToken();
-  parseLevel();
+  return parseLevel();
 }
 
-void UnwrappedLineParser::parseLevel() {
+bool UnwrappedLineParser::parseLevel() {
+  bool Error = false;
   do {
     switch (FormatTok.Tok.getKind()) {
     case tok::hash:
@@ -47,19 +48,20 @@
       parseComment();
       break;
     case tok::l_brace:
-      parseBlock();
+      Error |= parseBlock();
       addUnwrappedLine();
       break;
     case tok::r_brace:
-      return;
+      return false;
     default:
       parseStatement();
       break;
     }
   } while (!eof());
+  return Error;
 }
 
-void UnwrappedLineParser::parseBlock() {
+bool UnwrappedLineParser::parseBlock() {
   nextToken();
 
   // FIXME: Remove this hack to handle namespaces.
@@ -74,11 +76,12 @@
     --Line.Level;
   // FIXME: Add error handling.
   if (!FormatTok.Tok.is(tok::r_brace))
-    return;
+    return true;
 
   nextToken();
   if (FormatTok.Tok.is(tok::semi))
     nextToken();
+  return false;
 }
 
 void UnwrappedLineParser::parsePPDirective() {

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=169286&r1=169285&r2=169286&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.h (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.h Tue Dec  4 11:27:50 2012
@@ -79,11 +79,12 @@
   UnwrappedLineParser(Lexer &Lex, SourceManager &SourceMgr,
                       UnwrappedLineConsumer &Callback);
 
-  void parse();
+  /// Returns true in case of a structural error.
+  bool parse();
 
 private:
-  void parseLevel();
-  void parseBlock();
+  bool parseLevel();
+  bool parseBlock();
   void parsePPDirective();
   void parseComment();
   void parseStatement();

Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=169286&r1=169285&r2=169286&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Tue Dec  4 11:27:50 2012
@@ -381,5 +381,23 @@
                "};");
 }
 
+TEST_F(FormatTest, IncorrectCodeErrorDetection) {
+  EXPECT_EQ("{\n{\n}\n", format("{\n{\n}\n"));
+  EXPECT_EQ("{\n  {\n}\n", format("{\n  {\n}\n"));
+  EXPECT_EQ("{\n  {\n  }\n", format("{\n  {\n  }\n"));
+
+  FormatStyle Style = getLLVMStyle();
+  Style.ColumnLimit = 10;
+  EXPECT_EQ("{\n"
+            "    {\n"
+            " breakme(\n"
+            "     qwe);\n"
+            "}\n", format("{\n"
+                          "    {\n"
+                          " breakme(qwe);\n"
+                          "}\n", Style));
+
+}
+
 }  // end namespace tooling
 }  // end namespace clang





More information about the cfe-commits mailing list