r269748 - clang-format: [JS] simplify logic by parsing forward.

Martin Probst via cfe-commits cfe-commits at lists.llvm.org
Mon May 16 23:29:33 PDT 2016


Author: mprobst
Date: Tue May 17 01:29:33 2016
New Revision: 269748

URL: http://llvm.org/viewvc/llvm-project?rev=269748&view=rev
Log:
clang-format: [JS] simplify logic by parsing forward.

This also reduces complexity to O(n) from O(n^2) by avoiding backtracking
re-parses, and fixes length calculation.

Modified:
    cfe/trunk/lib/Format/Format.cpp

Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=269748&r1=269747&r2=269748&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Tue May 17 01:29:33 2016
@@ -807,8 +807,10 @@ public:
     assert(FirstInLineIndex == 0);
     do {
       Tokens.push_back(getNextToken());
-      if (Style.Language == FormatStyle::LK_JavaScript)
+      if (Style.Language == FormatStyle::LK_JavaScript) {
         tryParseJSRegexLiteral();
+        tryParseTemplateString();
+      }
       tryMergePreviousTokens();
       if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
         FirstInLineIndex = Tokens.size() - 1;
@@ -828,9 +830,6 @@ private:
       return;
 
     if (Style.Language == FormatStyle::LK_JavaScript) {
-      if (tryMergeTemplateString())
-        return;
-
       static const tok::TokenKind JSIdentity[] = {tok::equalequal, tok::equal};
       static const tok::TokenKind JSNotIdentity[] = {tok::exclaimequal,
                                                      tok::equal};
@@ -992,70 +991,42 @@ private:
     resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset)));
   }
 
-  bool tryMergeTemplateString() {
-    if (Tokens.size() < 2)
-      return false;
-
-    FormatToken *EndBacktick = Tokens.back();
-    // Backticks get lexed as tok::unknown tokens. If a template string contains
-    // a comment start, it gets lexed as a tok::comment, or tok::unknown if
-    // unterminated.
-    if (!EndBacktick->isOneOf(tok::comment, tok::string_literal,
-                              tok::char_constant, tok::unknown))
-      return false;
-    size_t CommentBacktickPos = EndBacktick->TokenText.find('`');
-    // Unknown token that's not actually a backtick, or a comment that doesn't
-    // contain a backtick.
-    if (CommentBacktickPos == StringRef::npos)
-      return false;
-
-    unsigned TokenCount = 0;
-    for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; I++) {
-      ++TokenCount;
-
-      // If there was a preceding template string, this must be the start of a
-      // template string, not the end.
-      if (I[0]->is(TT_TemplateString))
-        return false;
+  void tryParseTemplateString() {
+    FormatToken *BacktickToken = Tokens.back();
+    if (!BacktickToken->is(tok::unknown) || BacktickToken->TokenText != "`")
+      return;
 
-      if (I[0]->isNot(tok::unknown) || I[0]->TokenText != "`")
-        continue;
+    // 'Manually' lex ahead in the current file buffer.
+    const char *Offset = Lex->getBufferLocation();
+    const char *TmplBegin = Offset - BacktickToken->TokenText.size(); // at "`"
+    for (; Offset != Lex->getBuffer().end() && *Offset != '`'; ++Offset) {
+      if (*Offset == '\\')
+        ++Offset; // Skip the escaped character.
+    }
 
-      Tokens.resize(Tokens.size() - TokenCount);
-      FormatToken *TemplateStringToken = Tokens.back();
-      TemplateStringToken->Type = TT_TemplateString;
-      const char *EndOffset =
-          EndBacktick->TokenText.data() + 1 + CommentBacktickPos;
-      if (CommentBacktickPos != 0) {
-        // If the backtick was not the first character (e.g. in a comment),
-        // re-lex after the backtick position.
-        SourceLocation Loc = EndBacktick->Tok.getLocation();
-        resetLexer(SourceMgr.getFileOffset(Loc) + CommentBacktickPos + 1);
-      }
-      StringRef LiteralText =
-          StringRef(TemplateStringToken->TokenText.data(),
-                    EndOffset - TemplateStringToken->TokenText.data());
-      TemplateStringToken->TokenText = LiteralText;
-
-      size_t FirstBreak = LiteralText.find('\n');
-      StringRef FirstLineText = FirstBreak == StringRef::npos
-                                    ? LiteralText
-                                    : LiteralText.substr(0, FirstBreak);
-      TemplateStringToken->ColumnWidth = encoding::columnWidthWithTabs(
-          FirstLineText, TemplateStringToken->OriginalColumn, Style.TabWidth,
-          Encoding);
-      size_t LastBreak = LiteralText.rfind('\n');
-      if (LastBreak != StringRef::npos) {
-        TemplateStringToken->IsMultiline = true;
-        unsigned StartColumn = 0; // The template tail spans the entire line.
-        TemplateStringToken->LastLineColumnWidth =
-            encoding::columnWidthWithTabs(
-                LiteralText.substr(LastBreak + 1, LiteralText.size()),
-                StartColumn, Style.TabWidth, Encoding);
-      }
-      return true;
+    StringRef LiteralText(TmplBegin, Offset - TmplBegin + 1);
+    BacktickToken->Type = TT_TemplateString;
+    BacktickToken->Tok.setKind(tok::string_literal);
+    BacktickToken->TokenText = LiteralText;
+
+    // Adjust width for potentially multiline string literals.
+    size_t FirstBreak = LiteralText.find('\n');
+    StringRef FirstLineText = FirstBreak == StringRef::npos
+                                  ? LiteralText
+                                  : LiteralText.substr(0, FirstBreak);
+    BacktickToken->ColumnWidth = encoding::columnWidthWithTabs(
+        FirstLineText, BacktickToken->OriginalColumn, Style.TabWidth, Encoding);
+    size_t LastBreak = LiteralText.rfind('\n');
+    if (LastBreak != StringRef::npos) {
+      BacktickToken->IsMultiline = true;
+      unsigned StartColumn = 0; // The template tail spans the entire line.
+      BacktickToken->LastLineColumnWidth = encoding::columnWidthWithTabs(
+          LiteralText.substr(LastBreak + 1, LiteralText.size()), StartColumn,
+          Style.TabWidth, Encoding);
     }
-    return false;
+
+    resetLexer(
+        SourceMgr.getFileOffset(Lex->getSourceLocation(Offset + 1)));
   }
 
   bool tryMerge_TMacro() {




More information about the cfe-commits mailing list