Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -876,12 +876,23 @@ return false; unsigned TokenCount = 0; + auto InCharacterClass = false; for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) { ++TokenCount; auto Prev = I + 1; while (Prev != E && Prev[0]->is(tok::comment)) ++Prev; - if (I[0]->isOneOf(tok::slash, tok::slashequal) && + // Slashes in character classes (delimited by [ and ]) do not need + // escaping. Escaping of the squares themselves is already handled by + // \c tryMergeEscapeSequence(), a plain tok::r_square must be non-escaped. + if (I[0]->is(tok::r_square)) + InCharacterClass = true; + if (I[0]->is(tok::l_square)) { + if (!InCharacterClass) + return false; + InCharacterClass = false; + } + if (!InCharacterClass && I[0]->isOneOf(tok::slash, tok::slashequal) && (Prev == E || ((Prev[0]->isOneOf(tok::l_paren, tok::semi, tok::l_brace, tok::r_brace, tok::exclaim, tok::l_square, Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -617,9 +617,15 @@ verifyFormat("var regex = /x|y/;"); verifyFormat("var regex = /a{2}/;"); verifyFormat("var regex = /a{1,3}/;"); + verifyFormat("var regex = /[abc]/;"); verifyFormat("var regex = /[^abc]/;"); verifyFormat("var regex = /[\\b]/;"); + verifyFormat("var regex = /[/]/;"); + verifyFormat("var regex = /[\\/]/;"); + verifyFormat("var regex = /\\[/;"); + verifyFormat("var regex = /\\\\[/]/;"); + verifyFormat("var regex = /\\b/;"); verifyFormat("var regex = /\\B/;"); verifyFormat("var regex = /\\d/;");