diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2669,6 +2669,7 @@ bool isCpp() const { return Language == LK_Cpp || Language == LK_ObjC; } bool isCSharp() const { return Language == LK_CSharp; } bool isJson() const { return Language == LK_Json; } + bool isJavaScript() const { return Language == LK_JavaScript; } /// Language, this format style is targeted at. /// \version 3.5 diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1826,14 +1826,16 @@ if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof, Keywords.kw_as)) return false; - if (Style.Language == FormatStyle::LK_JavaScript && - Tok.Previous->is(Keywords.kw_in)) + if (Style.isJavaScript() && Tok.Previous->is(Keywords.kw_in)) return false; // Skip "const" as it does not have an influence on whether this is a name. FormatToken *PreviousNotConst = Tok.getPreviousNonComment(); - while (PreviousNotConst && PreviousNotConst->is(tok::kw_const)) - PreviousNotConst = PreviousNotConst->getPreviousNonComment(); + + // For javascript const can be like "let" or "var" + if (!Style.isJavaScript()) + while (PreviousNotConst && PreviousNotConst->is(tok::kw_const)) + PreviousNotConst = PreviousNotConst->getPreviousNonComment(); if (!PreviousNotConst) return false; @@ -1852,10 +1854,24 @@ PreviousNotConst->is(TT_TypeDeclarationParen)) return true; - return (!IsPPKeyword && - PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto)) || - PreviousNotConst->is(TT_PointerOrReference) || - PreviousNotConst->isSimpleTypeSpecifier(); + // If is a preprocess keyword like #define. + if (IsPPKeyword) + return false; + + // int a or auto a. + if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto)) + return true; + + // *a or &a or &&a. + if (PreviousNotConst->is(TT_PointerOrReference)) + return true; + + // MyClass a; + if (PreviousNotConst->isSimpleTypeSpecifier()) + return true; + + // const a = in JavaScript. + return (Style.isJavaScript() && PreviousNotConst->is(tok::kw_const)); } /// Determine whether ')' is ending a cast. diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp --- a/clang/unittests/Format/FormatTestJS.cpp +++ b/clang/unittests/Format/FormatTestJS.cpp @@ -2696,5 +2696,115 @@ verifyFormat("x = 1_000_000 + 12;", "x = 1_000_000 + 12;"); } +TEST_F(FormatTestJS, AlignConsecutiveDeclarations) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); + Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; + verifyFormat("let letVariable = 5;\n" + "double constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "const constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "static const constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "static var constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "var constVariable = 10;", + Style); + + verifyFormat("double letVariable = 5;\n" + "var constVariable = 10;", + Style); + + verifyFormat("const letVariable = 5;\n" + "var constVariable = 10;", + Style); + + verifyFormat("int letVariable = 5;\n" + "int constVariable = 10;", + Style); +} + +TEST_F(FormatTestJS, AlignConsecutiveAssignments) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); + + Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; + verifyFormat("let letVariable = 5;\n" + "double constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "const constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "static const constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "static var constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "var constVariable = 10;", + Style); + + verifyFormat("double letVariable = 5;\n" + "var constVariable = 10;", + Style); + + verifyFormat("const letVariable = 5;\n" + "var constVariable = 10;", + Style); + + verifyFormat("int letVariable = 5;\n" + "int constVariable = 10;", + Style); +} + +TEST_F(FormatTestJS, AlignConsecutiveAssignmentsAndDeclarations) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript); + Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; + Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; + verifyFormat("let letVariable = 5;\n" + "double constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "const constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "static const constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "static var constVariable = 10;", + Style); + + verifyFormat("let letVariable = 5;\n" + "var constVariable = 10;", + Style); + + verifyFormat("double letVariable = 5;\n" + "var constVariable = 10;", + Style); + + verifyFormat("const letVariable = 5;\n" + "var constVariable = 10;", + Style); + + verifyFormat("int letVariable = 5;\n" + "int constVariable = 10;", + Style); +} + } // namespace format } // end namespace clang