1 //===- unittest/Format/FormatTestJS.cpp - Formatting unit tests for JS ----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "FormatTestUtils.h" 11 #include "clang/Format/Format.h" 12 #include "llvm/Support/Debug.h" 13 #include "gtest/gtest.h" 14 15 #define DEBUG_TYPE "format-test" 16 17 namespace clang { 18 namespace format { 19 20 class FormatTestJS : public ::testing::Test { 21 protected: 22 static std::string format(llvm::StringRef Code, unsigned Offset, 23 unsigned Length, const FormatStyle &Style) { 24 DEBUG(llvm::errs() << "---\n"); 25 DEBUG(llvm::errs() << Code << "\n\n"); 26 std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length)); 27 tooling::Replacements Replaces = reformat(Style, Code, Ranges); 28 std::string Result = applyAllReplacements(Code, Replaces); 29 EXPECT_NE("", Result); 30 DEBUG(llvm::errs() << "\n" << Result << "\n\n"); 31 return Result; 32 } 33 34 static std::string format(llvm::StringRef Code, const FormatStyle &Style) { 35 return format(Code, 0, Code.size(), Style); 36 } 37 38 static FormatStyle getGoogleJSStyleWithColumns(unsigned ColumnLimit) { 39 FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); 40 Style.ColumnLimit = ColumnLimit; 41 return Style; 42 } 43 44 static void verifyFormat( 45 llvm::StringRef Code, 46 const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) { 47 EXPECT_EQ(Code.str(), format(test::messUp(Code), Style)); 48 } 49 }; 50 51 TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) { 52 verifyFormat("a == = b;"); 53 verifyFormat("a != = b;"); 54 55 verifyFormat("a === b;"); 56 verifyFormat("aaaaaaa ===\n b;", getGoogleJSStyleWithColumns(10)); 57 verifyFormat("a !== b;"); 58 verifyFormat("aaaaaaa !==\n b;", getGoogleJSStyleWithColumns(10)); 59 verifyFormat("if (a + b + c +\n" 60 " d !==\n" 61 " e + f + g)\n" 62 " q();", 63 getGoogleJSStyleWithColumns(20)); 64 65 verifyFormat("a >> >= b;"); 66 67 verifyFormat("a >>> b;"); 68 verifyFormat("aaaaaaa >>>\n b;", getGoogleJSStyleWithColumns(10)); 69 verifyFormat("a >>>= b;"); 70 verifyFormat("aaaaaaa >>>=\n b;", getGoogleJSStyleWithColumns(10)); 71 verifyFormat("if (a + b + c +\n" 72 " d >>>\n" 73 " e + f + g)\n" 74 " q();", 75 getGoogleJSStyleWithColumns(20)); 76 verifyFormat("var x = aaaaaaaaaa ?\n" 77 " bbbbbb :\n" 78 " ccc;", 79 getGoogleJSStyleWithColumns(20)); 80 } 81 82 TEST_F(FormatTestJS, SpacesInContainerLiterals) { 83 verifyFormat("var arr = [1, 2, 3];"); 84 verifyFormat("var obj = {a: 1, b: 2, c: 3};"); 85 86 verifyFormat("var obj = {a: 1, b: 2, c: 3};", 87 getChromiumStyle(FormatStyle::LK_JavaScript)); 88 } 89 90 TEST_F(FormatTestJS, SingleQuoteStrings) { 91 verifyFormat("this.function('', true);"); 92 } 93 94 TEST_F(FormatTestJS, GoogScopes) { 95 verifyFormat("goog.scope(function() {\n" 96 "var x = a.b;\n" 97 "var y = c.d;\n" 98 "}); // goog.scope"); 99 } 100 101 TEST_F(FormatTestJS, Closures) { 102 verifyFormat("doFoo(function() { return 1; });"); 103 verifyFormat("var func = function() { return 1; };"); 104 } 105 106 TEST_F(FormatTestJS, ReturnStatements) { 107 verifyFormat("function() { return [hello, world]; }"); 108 } 109 110 TEST_F(FormatTestJS, ClosureStyleComments) { 111 verifyFormat("var x = /** @type {foo} */ (bar);"); 112 } 113 114 TEST_F(FormatTestJS, RegexLiteralClassification) { 115 // Regex literals. 116 verifyFormat("var regex = /abc/;"); 117 verifyFormat("f(/abc/);"); 118 verifyFormat("f(abc, /abc/);"); 119 verifyFormat("some_map[/abc/];"); 120 verifyFormat("var x = a ? /abc/ : /abc/;"); 121 verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}"); 122 verifyFormat("var x = !/abc/.test(y);"); 123 verifyFormat("var x = a && /abc/.test(y);"); 124 verifyFormat("var x = a || /abc/.test(y);"); 125 verifyFormat("var x = a + /abc/.search(y);"); 126 127 // Not regex literals. 128 verifyFormat("var a = a / 2 + b / 3;"); 129 } 130 131 TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) { 132 verifyFormat("var regex = /a*/;"); 133 verifyFormat("var regex = /a+/;"); 134 verifyFormat("var regex = /a?/;"); 135 verifyFormat("var regex = /.a./;"); 136 verifyFormat("var regex = /a\\*/;"); 137 verifyFormat("var regex = /^a$/;"); 138 verifyFormat("var regex = /\\/a/;"); 139 verifyFormat("var regex = /(?:x)/;"); 140 verifyFormat("var regex = /x(?=y)/;"); 141 verifyFormat("var regex = /x(?!y)/;"); 142 verifyFormat("var regex = /x|y/;"); 143 verifyFormat("var regex = /a{2}/;"); 144 verifyFormat("var regex = /a{1,3}/;"); 145 verifyFormat("var regex = /[abc]/;"); 146 verifyFormat("var regex = /[^abc]/;"); 147 verifyFormat("var regex = /[\\b]/;"); 148 verifyFormat("var regex = /\\b/;"); 149 verifyFormat("var regex = /\\B/;"); 150 verifyFormat("var regex = /\\d/;"); 151 verifyFormat("var regex = /\\D/;"); 152 verifyFormat("var regex = /\\f/;"); 153 verifyFormat("var regex = /\\n/;"); 154 verifyFormat("var regex = /\\r/;"); 155 verifyFormat("var regex = /\\s/;"); 156 verifyFormat("var regex = /\\S/;"); 157 verifyFormat("var regex = /\\t/;"); 158 verifyFormat("var regex = /\\v/;"); 159 verifyFormat("var regex = /\\w/;"); 160 verifyFormat("var regex = /\\W/;"); 161 verifyFormat("var regex = /a(a)\\1/;"); 162 verifyFormat("var regex = /\\0/;"); 163 } 164 165 TEST_F(FormatTestJS, RegexLiteralModifiers) { 166 verifyFormat("var regex = /abc/g;"); 167 verifyFormat("var regex = /abc/i;"); 168 verifyFormat("var regex = /abc/m;"); 169 verifyFormat("var regex = /abc/y;"); 170 } 171 172 TEST_F(FormatTestJS, RegexLiteralLength) { 173 verifyFormat("var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;", 174 getGoogleJSStyleWithColumns(60)); 175 verifyFormat("var regex =\n" 176 " /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;", 177 getGoogleJSStyleWithColumns(60)); 178 } 179 180 TEST_F(FormatTestJS, RegexLiteralExamples) { 181 verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);"); 182 } 183 184 } // end namespace tooling 185 } // end namespace clang 186