[PATCH] D20632: clang-format: [JS] Support shebang lines on the very first line.

Martin Probst via cfe-commits cfe-commits at lists.llvm.org
Wed May 25 10:31:39 PDT 2016


mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

Shebang lines (`#!/bin/blah`) can be used in JavaScript scripts to indicate
they should be run using e.g. node. This change treats # lines on the first line
as line comments.

http://reviews.llvm.org/D20632

Files:
  lib/Format/FormatTokenLexer.cpp
  lib/Format/FormatTokenLexer.h
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===================================================================
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1272,5 +1272,12 @@
   verifyFormat("var x = 'foo';", LeaveQuotes);
 }
 
+TEST_F(FormatTestJS, SupportShebangLines) {
+  verifyFormat("#!/usr/bin/env node\n"
+               "var x = hello();",
+               "#!/usr/bin/env node\n"
+               "var x   =  hello();");
+}
+
 } // end namespace tooling
 } // end namespace clang
Index: lib/Format/FormatTokenLexer.h
===================================================================
--- lib/Format/FormatTokenLexer.h
+++ lib/Format/FormatTokenLexer.h
@@ -55,6 +55,8 @@
 
   void tryParseTemplateString();
 
+  void tryParseShebangLine();
+
   bool tryMerge_TMacro();
 
   bool tryMergeConflictMarkers();
Index: lib/Format/FormatTokenLexer.cpp
===================================================================
--- lib/Format/FormatTokenLexer.cpp
+++ lib/Format/FormatTokenLexer.cpp
@@ -20,6 +20,10 @@
 #include "clang/Format/Format.h"
 #include "llvm/Support/Regex.h"
 
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "format-formatter"
+
 namespace clang {
 namespace format {
 
@@ -50,8 +54,10 @@
     if (Style.Language == FormatStyle::LK_JavaScript) {
       tryParseJSRegexLiteral();
       tryParseTemplateString();
+      tryParseShebangLine();
     }
     tryMergePreviousTokens();
+
     if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
       FirstInLineIndex = Tokens.size() - 1;
   } while (Tokens.back()->Tok.isNot(tok::eof));
@@ -265,6 +271,31 @@
   resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset + 1)));
 }
 
+void FormatTokenLexer::tryParseShebangLine() {
+  if (Tokens.size() > 1)
+    // Must be the first token of the file.
+    return;
+  FormatToken *HashToken = Tokens.back();
+  if (!HashToken->is(tok::hash) || HashToken->TokenText != "#")
+    return;
+
+  // 'Manually' lex ahead in the current file buffer.
+  const char *Offset = Lex->getBufferLocation();
+  const char *ShebangBegin = Offset - HashToken->TokenText.size(); // at "#"
+  for (; Offset != Lex->getBuffer().end() && *Offset != '\n';)
+    ++Offset;
+
+  // ShebangText does *not* include the terminating '\n' so that the comment
+  // gets properly terminated.
+  StringRef ShebangText(ShebangBegin, Offset - ShebangBegin);
+  HashToken->Type = TT_Unknown;
+  HashToken->Tok.setKind(tok::comment);
+  HashToken->TokenText = ShebangText;
+  HashToken->ColumnWidth = ShebangText.size();
+
+  resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset)));
+}
+
 bool FormatTokenLexer::tryMerge_TMacro() {
   if (Tokens.size() < 4)
     return false;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D20632.58451.patch
Type: text/x-patch
Size: 2734 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160525/f4e0bf6d/attachment.bin>


More information about the cfe-commits mailing list