Index: lib/Format/FormatToken.h =================================================================== --- lib/Format/FormatToken.h +++ lib/Format/FormatToken.h @@ -537,6 +537,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"); @@ -583,6 +584,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 @@ -764,13 +764,29 @@ return LT_ImportStatement; } + // import {...} from '...'; + if (Style.Language == FormatStyle::LK_JavaScript && + CurrentToken->is(Keywords.kw_import)) + return LT_ImportStatement; + bool KeywordVirtualFound = false; bool ImportStatement = false; while (CurrentToken) { if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; - if (isImportStatement(*CurrentToken)) - ImportStatement = true; + if (Style.Language == FormatStyle::LK_JavaScript) { + // An export followed by "from 'some string';" is a re-export from + // another module identified by a URI and is treated as a + // LT_ImportStatement (i.e. prevent wraps on it for long URIs). + // Just "export {...};" or "export class ..." should not be treated as + // an import in this sense. + if (Line.First->is(tok::kw_export) && + CurrentToken->is(Keywords.kw_from) && CurrentToken->Next && + CurrentToken->Next->isStringLiteral()) + ImportStatement = true; + if (isClosureImportStatement(*CurrentToken)) + ImportStatement = true; + } if (!consumeToken()) return LT_Invalid; } @@ -790,11 +806,10 @@ } 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) && + 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 @@ -942,21 +942,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\n '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;"); @@ -970,10 +959,19 @@ verifyFormat("export const x = 12;"); verifyFormat("export default class X {}"); verifyFormat("export {X, Y} 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;"); + // ... but not if from is just an identifier. verifyFormat("export {\n" - " X,\n" - " Y,\n" - "} from 'some/module.js';"); + " from as from,\n" + " someSurprisinglyLongVariable\n" + " as from\n" + "};", + getGoogleJSStyleWithColumns(20)); verifyFormat("export class C {\n" " x: number;\n" " y: string;\n"