Index: lib/Format/FormatToken.h =================================================================== --- lib/Format/FormatToken.h +++ lib/Format/FormatToken.h @@ -536,6 +536,7 @@ kw_finally = &IdentTable.get("finally"); kw_function = &IdentTable.get("function"); + kw_from = &IdentTable.get("from"); kw_import = &IdentTable.get("import"); kw_is = &IdentTable.get("is"); kw_let = &IdentTable.get("let"); @@ -582,6 +583,7 @@ // JavaScript keywords. IdentifierInfo *kw_finally; IdentifierInfo *kw_function; + IdentifierInfo *kw_from; IdentifierInfo *kw_import; IdentifierInfo *kw_is; IdentifierInfo *kw_let; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -752,12 +752,31 @@ return LT_ImportStatement; } + if (Style.Language == FormatStyle::LK_JavaScript) { + // import {...} from '...'; + if (CurrentToken->is(Keywords.kw_import)) + return LT_ImportStatement; + if (CurrentToken->is(tok::kw_export)) { + // Find the 'from' part of export {...} from '...'; + // The difference here is that "export {...};" should not be treated as + // an export. + while (CurrentToken) { + if (CurrentToken->is(tok::semi)) + return LT_Other; + if (CurrentToken->is(Keywords.kw_from)) + return LT_ImportStatement; + if (!consumeToken()) + return LT_Invalid; + } + } + } + bool KeywordVirtualFound = false; bool ImportStatement = false; while (CurrentToken) { if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; - if (isImportStatement(*CurrentToken)) + if (isClosureImportStatement(*CurrentToken)) ImportStatement = true; if (!consumeToken()) return LT_Invalid; @@ -778,11 +797,12 @@ } private: - bool isImportStatement(const FormatToken &Tok) { + bool isClosureImportStatement(const FormatToken &Tok) { // FIXME: Closure-library specific stuff should not be hard-coded but be // configurable. - return Style.Language == FormatStyle::LK_JavaScript && - Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) && + if (Style.Language != FormatStyle::LK_JavaScript) + return false; + return Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) && Tok.Next->Next && (Tok.Next->Next->TokenText == "module" || Tok.Next->Next->TokenText == "provide" || Tok.Next->Next->TokenText == "require" || Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -861,21 +861,10 @@ verifyFormat("import SomeThing from 'some/module.js';"); verifyFormat("import {X, Y} from 'some/module.js';"); verifyFormat("import a, {X, Y} from 'some/module.js';"); - verifyFormat("import {\n" - " VeryLongImportsAreAnnoying,\n" - " VeryLongImportsAreAnnoying,\n" - " VeryLongImportsAreAnnoying,\n" - " VeryLongImportsAreAnnoying\n" + verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying," + " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying" "} from 'some/module.js';"); - verifyFormat("import {\n" - " X,\n" - " Y,\n" - "} from 'some/module.js';"); - verifyFormat("import {\n" - " X,\n" - " Y,\n" - "} from 'some/long/module.js';", - getGoogleJSStyleWithColumns(20)); + verifyFormat("import {X, Y,} from 'some/module.js';"); verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';"); verifyFormat("import * as lib from 'some/module.js';"); verifyFormat("var x = {import: 1};\nx.import = 2;"); @@ -889,10 +878,12 @@ 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 {X, Y,} from 'some/module.js';"); + verifyFormat("export {SomeVeryLongExport as X, " + "SomeOtherVeryLongExport as Y} from 'some/module.js';"); + // export without 'from' is wrapped. + verifyFormat("export let someRatherLongVariableName =\n" + " someSurprisinglyLongVariable + someOtherRatherLongVar;"); verifyFormat("export class C {\n" " x: number;\n" " y: string;\n"