Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -1759,7 +1759,7 @@ if (Right.is(TT_JsTypeColon)) return false; if ((Left.is(tok::l_brace) || Right.is(tok::r_brace)) && - Line.First->is(Keywords.kw_import)) + Line.First->isOneOf(Keywords.kw_import, tok::kw_export)) return false; } else if (Style.Language == FormatStyle::LK_Java) { if (Left.is(tok::r_square) && Right.is(tok::l_brace)) Index: lib/Format/UnwrappedLineParser.h =================================================================== --- lib/Format/UnwrappedLineParser.h +++ lib/Format/UnwrappedLineParser.h @@ -103,7 +103,7 @@ void parseObjCUntilAtEnd(); void parseObjCInterfaceOrImplementation(); void parseObjCProtocol(); - void parseJavaScriptEs6Import(); + void parseJavaScriptEs6ImportExport(); bool tryToParseLambda(); bool tryToParseLambdaIntroducer(); void tryToParseJSFunction(); Index: lib/Format/UnwrappedLineParser.cpp =================================================================== --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -262,7 +262,7 @@ void UnwrappedLineParser::parseFile() { ScopedDeclarationState DeclarationState( *Line, DeclarationScopeStack, - /*MustBeDeclaration=*/ !Line->InPPDirective); + /*MustBeDeclaration=*/!Line->InPPDirective); parseLevel(/*HasOpeningBrace=*/false); // Make sure to format the remaining tokens. flushComments(true); @@ -734,6 +734,12 @@ } } break; + case tok::kw_export: + if (Style.Language == FormatStyle::LK_JavaScript) { + parseJavaScriptEs6ImportExport(); + return; + } + break; case tok::identifier: if (FormatTok->IsForEachMacro) { parseForOrWhileLoop(); @@ -741,7 +747,7 @@ } if (Style.Language == FormatStyle::LK_JavaScript && FormatTok->is(Keywords.kw_import)) { - parseJavaScriptEs6Import(); + parseJavaScriptEs6ImportExport(); return; } // In all other cases, parse the declaration. @@ -970,7 +976,7 @@ // Consume function name. if (FormatTok->is(tok::identifier)) - nextToken(); + nextToken(); if (FormatTok->isNot(tok::l_paren)) return; @@ -1603,13 +1609,24 @@ parseObjCUntilAtEnd(); } -void UnwrappedLineParser::parseJavaScriptEs6Import() { - assert(FormatTok->is(Keywords.kw_import)); +void UnwrappedLineParser::parseJavaScriptEs6ImportExport() { + assert(FormatTok->isOneOf(Keywords.kw_import, tok::kw_export)); nextToken(); - if (FormatTok->is(tok::l_brace)) { + + if (FormatTok->isOneOf(tok::kw_const, tok::kw_class, Keywords.kw_function, + Keywords.kw_var)) + return; // Fall through to parsing the corresponding structure. + + if (FormatTok->is(tok::kw_default)) { + nextToken(); // export default ..., fall through after eating 'default'. + return; + } + + if (FormatTok->is(tok::l_brace) { FormatTok->BlockKind = BK_Block; parseBracedList(); } + while (!eof() && FormatTok->isNot(tok::semi) && FormatTok->isNot(tok::l_brace)) { nextToken(); Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -544,9 +544,30 @@ verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';"); verifyFormat("import * as lib from 'some/module.js';"); verifyFormat("var x = {\n import: 1\n};\nx.import = 2;"); - verifyFormat("export function fn() {\n return 'fn';\n}"); + + verifyFormat("export function fn() {\n" + " return 'fn';\n" + "}"); verifyFormat("export const x = 12;"); verifyFormat("export default class X {}"); + verifyFormat("export {X, Y} from 'some/module.js';"); + verifyFormat("export {\n" + " X,\n" + " Y,\n" + "} from 'some/module.js';"); + verifyFormat("export class C {\n" + " x: number;\n" + " y: string;\n" + "}"); + verifyFormat("export class X { y: number; }"); + verifyFormat("export default class X { y: number }"); + verifyFormat("export default function() {\n return 1;\n}"); + verifyFormat("export var x = 12;"); + verifyFormat("export var x: number = 12;"); + verifyFormat("export const y = {\n" + " a: 1,\n" + " b: 2\n" + "};"); } } // end namespace tooling