mprobst updated this revision to Diff 48338.
mprobst added a comment.
Fixed typo.
http://reviews.llvm.org/D17385
Files:
lib/Format/Format.cpp
unittests/Format/FormatTestJS.cpp
Index: unittests/Format/FormatTestJS.cpp
===================================================================
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -250,7 +250,7 @@
verifyFormat("f({'a': [{}]});");
}
-TEST_F(FormatTestJS, SingleQuoteStrings) {
+TEST_F(FormatTestJS, SingleQuotedStrings) {
verifyFormat("this.function('', true);");
}
@@ -1085,5 +1085,16 @@
getGoogleJSStyleWithColumns(20)));
}
+TEST_F(FormatTestJS, RequoteDoubleQuotedStrings) {
+ EXPECT_EQ("var x = 'foo';", format("var x = \"foo\";"));
+ EXPECT_EQ("var x = 'fo\\'o\\'';", format("var x = \"fo'o'\";"));
+ EXPECT_EQ("var x = 'fo\\'o\\'';", format("var x = \"fo\\'o'\";"));
+ EXPECT_EQ("var x =\n"
+ " 'foo\\'';",
+ // Code below is 15 chars wide, doesn't fit into the line with the
+ // \ escape added.
+ format("var x = \"foo'\";", getGoogleJSStyleWithColumns(15)));
+}
+
} // end namespace tooling
} // end namespace clang
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -30,6 +30,7 @@
#include "llvm/Support/Regex.h"
#include "llvm/Support/YAMLTraits.h"
#include <queue>
+#include <sstream>
#include <string>
#define DEBUG_TYPE "format-formatter"
@@ -1328,6 +1329,35 @@
Column = FormatTok->LastLineColumnWidth;
}
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ FormatTok->isStringLiteral() && FormatTok->TokenText.startswith("\"")) {
+ // Double quoted JavaScript strings get requoted as single quoted below.
+ // For formatting, count the number of non-escaped single quotes in them
+ // and adjust ColumnWidth to take the later added escapes into account.
+
+ StringRef Input = FormatTok->TokenText;
+ bool Escaped = false;
+ size_t ColumnWidth = FormatTok->TokenText.size();
+ for (size_t i = 0; i != Input.size(); ++i) {
+ switch (Input[i]) {
+ case '\\':
+ Escaped = !Escaped;
+ break;
+ case '\'':
+ if (!Escaped) {
+ // Will later need to insert a \ to escape the double quote.
+ ColumnWidth++;
+ }
+ Escaped = false;
+ break;
+ default:
+ Escaped = false;
+ break;
+ }
+ }
+ FormatTok->ColumnWidth = ColumnWidth;
+ }
+
if (Style.Language == FormatStyle::LK_Cpp) {
if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() &&
Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() ==
@@ -1495,7 +1525,12 @@
UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(),
IncompleteFormat)
.format(AnnotatedLines);
- return Whitespaces.generateReplacements();
+ tooling::Replacements Replaces = Whitespaces.generateReplacements();
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ FormatToken *Tok = (*AnnotatedLines.begin())->First;
+ requoteJSStringLiterals(Replaces, Tok);
+ }
+ return Replaces;
}
private:
@@ -1538,6 +1573,42 @@
return SomeLineAffected;
}
+ // Finds all double-quoted string literals, and replaces them with single
+ // quoted string literals, escaping the contents in the process.
+ // The width of the extra \ escapes is taken into account in getNextToken.
+ void requoteJSStringLiterals(tooling::Replacements &Replaces,
+ FormatToken *Current) {
+ for (; Current != nullptr; Current = Current->Next) {
+ if (!Current->isStringLiteral() || !Current->TokenText.startswith("\""))
+ continue;
+ StringRef Input = Current->TokenText;
+ std::stringstream Res;
+ Res << '\'';
+ bool escaped = false;
+ for (size_t i = 1; i < Input.size() - 1; i++) {
+ switch (Input[i]) {
+ case '\\':
+ escaped = !escaped;
+ break;
+ case '\'':
+ if (!escaped) {
+ Res << '\\';
+ }
+ escaped = false;
+ break;
+ default:
+ escaped = false;
+ break;
+ }
+ Res << Input[i];
+ }
+ Res << '\'';
+ SourceRange Range(Current->Tok.getLocation(), Current->Tok.getEndLoc());
+ Replaces.insert(tooling::Replacement(
+ SourceMgr, CharSourceRange::getCharRange(Range), Res.str()));
+ }
+ }
+
// Determines whether 'Line' is affected by the SourceRanges given as input.
// Returns \c true if line or one if its children is affected.
bool nonPPLineAffected(AnnotatedLine *Line,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits