@@ -1150,7 +1150,6 @@ private void testInternal(
11501150
11511151 int numRepetitions = getNumRepetitions ();
11521152 ErrorManager [] errorManagers = new ErrorManager [numRepetitions ];
1153- int aggregateWarningCount = 0 ;
11541153 List <JSError > aggregateWarnings = new ArrayList <>();
11551154 boolean hasCodeChanged = false ;
11561155
@@ -1339,7 +1338,6 @@ private void testInternal(
13391338 }
13401339
13411340 hasCodeChanged = hasCodeChanged || recentChange .hasCodeChanged ();
1342- aggregateWarningCount += errorManagers [i ].getWarningCount ();
13431341 aggregateWarnings .addAll (compiler .getWarnings ());
13441342
13451343 if (normalizeEnabled ) {
@@ -1353,45 +1351,10 @@ private void testInternal(
13531351 if (expectedErrors .isEmpty ()) {
13541352 assertThat (compiler .getErrors ()).isEmpty ();
13551353
1356- // Verify the symbol table.
1357- ErrorManager symbolTableErrorManager = new BlackHoleErrorManager ();
1358- compiler .setErrorManager (symbolTableErrorManager );
1359- Node expectedRoot = null ;
1360- if (expected != null ) {
1361- expectedRoot = parseExpectedJs (expected );
1362- }
1354+ validateWarnings (
1355+ compiler , expectedWarnings , errorManagers , aggregateWarnings , numRepetitions );
13631356
1364- ImmutableList <JSError > stErrors = symbolTableErrorManager .getErrors ();
1365- if (expectedSymbolTableError != null ) {
1366- assertError (getOnlyElement (stErrors )).hasType (expectedSymbolTableError );
1367- } else {
1368- assertWithMessage ("symbol table errors" ).that (stErrors ).isEmpty ();
1369- }
1370- LightweightMessageFormatter formatter = new LightweightMessageFormatter (compiler );
1371- if (expectedWarnings .isEmpty ()) {
1372- assertWithMessage (
1373- "aggregate warnings: %s" ,
1374- aggregateWarnings .stream ().map (formatter ::formatWarning ).collect (joining ("\n " )))
1375- .that (aggregateWarnings )
1376- .isEmpty ();
1377- } else {
1378- assertWithMessage (
1379- "There should be %s warnings, repeated %s time(s). Warnings: \n %s" ,
1380- expectedWarnings .size (), numRepetitions , LINE_JOINER .join (aggregateWarnings ))
1381- .that (aggregateWarningCount )
1382- .isEqualTo (numRepetitions * expectedWarnings .size ());
1383- for (int i = 0 ; i < numRepetitions ; i ++) {
1384- assertWithMessage ("compile warnings from repetition %s" , (i + 1 ))
1385- .that (errorManagers [i ].getWarnings ())
1386- .comparingElementsUsing (DIAGNOSTIC_CORRESPONDENCE )
1387- .containsExactlyElementsIn (expectedWarnings );
1388- for (JSError warning : errorManagers [i ].getWarnings ()) {
1389- validateSourceLocation (warning );
1390- }
1391- }
1392- }
1393-
1394- // If we ran normalize on the AST, we must also run normalize on th clone before checking for
1357+ // If we ran normalize on the AST, we must also run normalize on the clone before checking for
13951358 // changes.
13961359 if (normalizeEnabled ) {
13971360 boolean hasTypecheckingRun = compiler .hasTypeCheckingRun ();
@@ -1402,92 +1365,21 @@ private void testInternal(
14021365 compiler .setTypeCheckingHasRun (hasTypecheckingRun );
14031366 }
14041367
1405- boolean codeChange = !mainRootClone .isEquivalentWithSideEffectsTo (mainRoot );
1406- boolean externsChange = !externsRootClone .isEquivalentWithSideEffectsTo (externsRoot );
1407-
1408- // Generally, externs should not be changed by the compiler passes.
1409- if (externsChange && !allowExternsChanges ) {
1410- assertNode (externsRoot )
1411- .usingSerializer (createPrettyPrinter (compiler ))
1412- .isEqualTo (externsRootClone );
1413- }
1414-
1415- if (checkAstChangeMarking ) {
1416- if (!codeChange && !externsChange ) {
1417- assertWithMessage ("compiler.reportCodeChange() was called even though nothing changed" )
1418- .that (hasCodeChanged )
1419- .isFalse ();
1420- } else {
1421- assertWithMessage (
1422- "compiler.reportCodeChange() should have been called."
1423- + "\n Original: %s\n New: %s" ,
1424- mainRootClone .toStringTree (), mainRoot .toStringTree ())
1425- .that (hasCodeChanged )
1426- .isTrue ();
1427- }
1368+ if (checkAstChangeMarking || !allowExternsChanges ) {
1369+ validateCodeChangeReporting (
1370+ mainRoot , externsRoot , mainRootClone , externsRootClone , compiler , hasCodeChanged );
14281371 }
14291372
14301373 if (expected != null ) {
1431- if (!compareSyntheticCode ) {
1432- Node scriptRoot = mainRoot .getFirstChild ();
1433- for (Node child = scriptRoot .getFirstChild (); child != null ; ) {
1434- Node nextChild = child .getNext ();
1435- if (NodeUtil .isInSyntheticScript (child )) {
1436- child .detach ();
1437- }
1438- child = nextChild ;
1439- }
1440- }
1374+ Node expectedRoot = parseExpectedJs (expected );
14411375 if (compareAsTree ) {
1442- if (compareJsDoc ) {
1443- assertNode (mainRoot )
1444- .usingSerializer (createPrettyPrinter (compiler ))
1445- .withGenericNameReplacements (ImmutableMap .copyOf (genericNameMapping ))
1446- .isEqualIncludingJsDocTo (expectedRoot );
1447- } else {
1448- assertNode (mainRoot )
1449- .usingSerializer (createPrettyPrinter (compiler ))
1450- .withGenericNameReplacements (ImmutableMap .copyOf (genericNameMapping ))
1451- .isEqualTo (expectedRoot );
1452- }
1376+ compareExpectedToActualAsTree (mainRoot , expectedRoot , compiler , genericNameMapping );
14531377 } else {
1454- String [] expectedSources = new String [expected .size ()];
1455- for (int i = 0 ; i < expected .size (); ++i ) {
1456- try {
1457- expectedSources [i ] = expected .get (i ).getCode ();
1458- } catch (IOException e ) {
1459- throw new RuntimeException ("failed to get source code" , e );
1460- }
1461- }
1462- assertThat (compiler .toSource (mainRoot ).replaceAll (" +\n " , "\n " ))
1463- .isEqualTo (Joiner .on ("" ).join (expectedSources ));
1378+ compareExpectedToActualAsStrings (mainRoot , compiler , expected );
14641379 }
14651380 }
14661381
1467- // Verify normalization is not invalidated.
1468- Node normalizeCheckRootClone = root .cloneTree ();
1469- Node normalizeCheckExternsRootClone = normalizeCheckRootClone .getFirstChild ();
1470- Node normalizeCheckMainRootClone = normalizeCheckRootClone .getLastChild ();
1471-
1472- assertNode (normalizeCheckMainRootClone )
1473- .usingSerializer (createPrettyPrinter (compiler ))
1474- .isEqualTo (mainRoot );
1475-
1476- // TODO(johnlenz): enable this for most test cases.
1477- // Currently, this invalidates test for while-loops, for-loop
1478- // initializers, and other naming. However, a set of code
1479- // (Closure primitive rewrites, etc) runs before the Normalize pass,
1480- // so this can't be force on everywhere.
1481- if (normalizeEnabled ) {
1482- Normalize .builder (compiler )
1483- .assertOnChange (true )
1484- .build ()
1485- .process (normalizeCheckExternsRootClone , normalizeCheckMainRootClone );
1486-
1487- assertNode (normalizeCheckMainRootClone )
1488- .usingSerializer (createPrettyPrinter (compiler ))
1489- .isEqualTo (mainRoot );
1490- }
1382+ validateNormalizationInvariants (root , compiler );
14911383 } else {
14921384 assertWithMessage ("compile errors" )
14931385 .that (compiler .getErrors ())
@@ -1560,6 +1452,148 @@ private void transpileToEs5(AbstractCompiler compiler, Node externsRoot, Node co
15601452 }
15611453 }
15621454
1455+ private void validateWarnings (
1456+ Compiler compiler ,
1457+ List <Diagnostic > expectedWarnings ,
1458+ ErrorManager [] errorManagers ,
1459+ List <JSError > aggregateWarnings ,
1460+ int numRepetitions ) {
1461+ // Verify the symbol table.
1462+ // TODO: lharker - why is this necessary?
1463+ ErrorManager symbolTableErrorManager = new BlackHoleErrorManager ();
1464+ compiler .setErrorManager (symbolTableErrorManager );
1465+
1466+ ImmutableList <JSError > stErrors = symbolTableErrorManager .getErrors ();
1467+ if (expectedSymbolTableError != null ) {
1468+ assertError (getOnlyElement (stErrors )).hasType (expectedSymbolTableError );
1469+ } else {
1470+ assertWithMessage ("symbol table errors" ).that (stErrors ).isEmpty ();
1471+ }
1472+
1473+ LightweightMessageFormatter formatter = new LightweightMessageFormatter (compiler );
1474+ if (expectedWarnings .isEmpty ()) {
1475+ assertWithMessage (
1476+ "aggregate warnings: %s" ,
1477+ aggregateWarnings .stream ().map (formatter ::formatWarning ).collect (joining ("\n " )))
1478+ .that (aggregateWarnings )
1479+ .isEmpty ();
1480+ } else {
1481+ assertWithMessage (
1482+ "There should be %s warnings, repeated %s time(s). Warnings: \n %s" ,
1483+ expectedWarnings .size (), numRepetitions , LINE_JOINER .join (aggregateWarnings ))
1484+ .that (aggregateWarnings .size ())
1485+ .isEqualTo (numRepetitions * expectedWarnings .size ());
1486+ for (int i = 0 ; i < numRepetitions ; i ++) {
1487+ assertWithMessage ("compile warnings from repetition %s" , (i + 1 ))
1488+ .that (errorManagers [i ].getWarnings ())
1489+ .comparingElementsUsing (DIAGNOSTIC_CORRESPONDENCE )
1490+ .containsExactlyElementsIn (expectedWarnings );
1491+ for (JSError warning : errorManagers [i ].getWarnings ()) {
1492+ validateSourceLocation (warning );
1493+ }
1494+ }
1495+ }
1496+ }
1497+
1498+ private void validateCodeChangeReporting (
1499+ Node mainRoot ,
1500+ Node externsRoot ,
1501+ Node mainRootClone ,
1502+ Node externsRootClone ,
1503+ Compiler compiler ,
1504+ boolean wasCodeChangeReported ) {
1505+ boolean codeChange = !mainRootClone .isEquivalentWithSideEffectsTo (mainRoot );
1506+ boolean externsChange = !externsRootClone .isEquivalentWithSideEffectsTo (externsRoot );
1507+
1508+ // Generally, externs should not be changed by the compiler passes.
1509+ if (externsChange && !allowExternsChanges ) {
1510+ assertNode (externsRoot )
1511+ .usingSerializer (createPrettyPrinter (compiler ))
1512+ .isEqualTo (externsRootClone );
1513+ }
1514+ if (checkAstChangeMarking ) {
1515+ if (!codeChange && !externsChange ) {
1516+ assertWithMessage ("compiler.reportCodeChange() was called even though nothing changed" )
1517+ .that (wasCodeChangeReported )
1518+ .isFalse ();
1519+ } else {
1520+ assertWithMessage (
1521+ "compiler.reportCodeChange() should have been called." + "\n Original: %s\n New: %s" ,
1522+ mainRootClone .toStringTree (), mainRoot .toStringTree ())
1523+ .that (wasCodeChangeReported )
1524+ .isTrue ();
1525+ }
1526+ }
1527+ }
1528+
1529+ private void compareExpectedToActualAsTree (
1530+ Node mainRoot , Node expectedRoot , Compiler compiler , Map <String , String > genericNameMapping ) {
1531+ if (!compareSyntheticCode ) {
1532+ Node scriptRoot = mainRoot .getFirstChild ();
1533+ for (Node child = scriptRoot .getFirstChild (); child != null ; ) {
1534+ Node nextChild = child .getNext ();
1535+ if (NodeUtil .isInSyntheticScript (child )) {
1536+ child .detach ();
1537+ }
1538+ child = nextChild ;
1539+ }
1540+ }
1541+ if (compareJsDoc ) {
1542+ assertNode (mainRoot )
1543+ .usingSerializer (createPrettyPrinter (compiler ))
1544+ .withGenericNameReplacements (ImmutableMap .copyOf (genericNameMapping ))
1545+ .isEqualIncludingJsDocTo (expectedRoot );
1546+ } else {
1547+ assertNode (mainRoot )
1548+ .usingSerializer (createPrettyPrinter (compiler ))
1549+ .withGenericNameReplacements (ImmutableMap .copyOf (genericNameMapping ))
1550+ .isEqualTo (expectedRoot );
1551+ }
1552+ }
1553+
1554+ private void compareExpectedToActualAsStrings (
1555+ Node mainRoot , Compiler compiler , List <SourceFile > expected ) {
1556+ String [] expectedSources = new String [expected .size ()];
1557+ for (int i = 0 ; i < expected .size (); ++i ) {
1558+ try {
1559+ expectedSources [i ] = expected .get (i ).getCode ();
1560+ } catch (IOException e ) {
1561+ throw new RuntimeException ("failed to get source code" , e );
1562+ }
1563+ }
1564+ assertThat (compiler .toSource (mainRoot ).replaceAll (" +\n " , "\n " ))
1565+ .isEqualTo (Joiner .on ("" ).join (expectedSources ));
1566+ }
1567+
1568+ private void validateNormalizationInvariants (Node root , Compiler compiler ) {
1569+ Node mainRoot = root .getLastChild ();
1570+
1571+ // Verify normalization is not invalidated.
1572+ Node normalizeCheckRootClone = root .cloneTree ();
1573+ Node normalizeCheckExternsRootClone = normalizeCheckRootClone .getFirstChild ();
1574+ Node normalizeCheckMainRootClone = normalizeCheckRootClone .getLastChild ();
1575+
1576+ assertNode (normalizeCheckMainRootClone )
1577+ .usingSerializer (createPrettyPrinter (compiler ))
1578+ .isEqualTo (mainRoot );
1579+
1580+ // TODO(johnlenz): enable this for most test cases.
1581+ // Currently, this invalidates test for while-loops, for-loop
1582+ // initializers, and other naming. However, a set of code
1583+ // (Closure primitive rewrites, etc) runs before the Normalize pass,
1584+ // so this can't be force on everywhere.
1585+ if (normalizeEnabled ) {
1586+ Normalize .builder (compiler )
1587+ .assertOnChange (true )
1588+ .build ()
1589+ .process (normalizeCheckExternsRootClone , normalizeCheckMainRootClone );
1590+
1591+ assertNode (normalizeCheckMainRootClone )
1592+ .usingSerializer (createPrettyPrinter (compiler ))
1593+ .isEqualTo (mainRoot );
1594+ }
1595+ }
1596+
15631597 private void validateSourceLocation (JSError jserror ) {
15641598 // Make sure that source information is always provided.
15651599 if (!allowSourcelessWarnings ) {
0 commit comments