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 verifyFormat("someVariable = {'a': [{}]};"); 89 } 90 91 TEST_F(FormatTestJS, SingleQuoteStrings) { 92 verifyFormat("this.function('', true);"); 93 } 94 95 TEST_F(FormatTestJS, GoogScopes) { 96 verifyFormat("goog.scope(function() {\n" 97 "var x = a.b;\n" 98 "var y = c.d;\n" 99 "}); // goog.scope"); 100 } 101 102 TEST_F(FormatTestJS, Closures) { 103 verifyFormat("doFoo(function() { return 1; });"); 104 verifyFormat("var func = function() { return 1; };"); 105 verifyFormat("return {\n" 106 " body: {\n" 107 " setAttribute: function(key, val) { this[key] = val; },\n" 108 " getAttribute: function(key) { return this[key]; },\n" 109 " style: {direction: ''}\n" 110 " }\n" 111 "};"); 112 } 113 114 TEST_F(FormatTestJS, ReturnStatements) { 115 verifyFormat("function() { return [hello, world]; }"); 116 } 117 118 TEST_F(FormatTestJS, ClosureStyleComments) { 119 verifyFormat("var x = /** @type {foo} */ (bar);"); 120 } 121 122 TEST_F(FormatTestJS, TryCatch) { 123 verifyFormat("try {\n" 124 " f();\n" 125 "} catch (e) {\n" 126 " g();\n" 127 "} finally {\n" 128 " h();\n" 129 "}"); 130 } 131 132 TEST_F(FormatTestJS, RegexLiteralClassification) { 133 // Regex literals. 134 verifyFormat("var regex = /abc/;"); 135 verifyFormat("f(/abc/);"); 136 verifyFormat("f(abc, /abc/);"); 137 verifyFormat("some_map[/abc/];"); 138 verifyFormat("var x = a ? /abc/ : /abc/;"); 139 verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}"); 140 verifyFormat("var x = !/abc/.test(y);"); 141 verifyFormat("var x = a && /abc/.test(y);"); 142 verifyFormat("var x = a || /abc/.test(y);"); 143 verifyFormat("var x = a + /abc/.search(y);"); 144 verifyFormat("var regexs = {/abc/, /abc/};"); 145 verifyFormat("return /abc/;"); 146 147 // Not regex literals. 148 verifyFormat("var a = a / 2 + b / 3;"); 149 } 150 151 TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) { 152 verifyFormat("var regex = /a*/;"); 153 verifyFormat("var regex = /a+/;"); 154 verifyFormat("var regex = /a?/;"); 155 verifyFormat("var regex = /.a./;"); 156 verifyFormat("var regex = /a\\*/;"); 157 verifyFormat("var regex = /^a$/;"); 158 verifyFormat("var regex = /\\/a/;"); 159 verifyFormat("var regex = /(?:x)/;"); 160 verifyFormat("var regex = /x(?=y)/;"); 161 verifyFormat("var regex = /x(?!y)/;"); 162 verifyFormat("var regex = /x|y/;"); 163 verifyFormat("var regex = /a{2}/;"); 164 verifyFormat("var regex = /a{1,3}/;"); 165 verifyFormat("var regex = /[abc]/;"); 166 verifyFormat("var regex = /[^abc]/;"); 167 verifyFormat("var regex = /[\\b]/;"); 168 verifyFormat("var regex = /\\b/;"); 169 verifyFormat("var regex = /\\B/;"); 170 verifyFormat("var regex = /\\d/;"); 171 verifyFormat("var regex = /\\D/;"); 172 verifyFormat("var regex = /\\f/;"); 173 verifyFormat("var regex = /\\n/;"); 174 verifyFormat("var regex = /\\r/;"); 175 verifyFormat("var regex = /\\s/;"); 176 verifyFormat("var regex = /\\S/;"); 177 verifyFormat("var regex = /\\t/;"); 178 verifyFormat("var regex = /\\v/;"); 179 verifyFormat("var regex = /\\w/;"); 180 verifyFormat("var regex = /\\W/;"); 181 verifyFormat("var regex = /a(a)\\1/;"); 182 verifyFormat("var regex = /\\0/;"); 183 verifyFormat("var regex = /\\\\/g;"); 184 verifyFormat("var regex = /\\a\\\\/g;"); 185 verifyFormat("var regex = /\a\\//g;"); 186 } 187 188 TEST_F(FormatTestJS, RegexLiteralModifiers) { 189 verifyFormat("var regex = /abc/g;"); 190 verifyFormat("var regex = /abc/i;"); 191 verifyFormat("var regex = /abc/m;"); 192 verifyFormat("var regex = /abc/y;"); 193 } 194 195 TEST_F(FormatTestJS, RegexLiteralLength) { 196 verifyFormat("var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;", 197 getGoogleJSStyleWithColumns(60)); 198 verifyFormat("var regex =\n" 199 " /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;", 200 getGoogleJSStyleWithColumns(60)); 201 } 202 203 TEST_F(FormatTestJS, RegexLiteralExamples) { 204 verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);"); 205 } 206 207 } // end namespace tooling 208 } // end namespace clang 209