Skip to content

Commit fbd722a

Browse files
committed
Factor out common logic in AbstractCommandLineRunner
This is mostly a no-op - the only change should be that now compiler.performPostCompilationTasks(); is consistently called even if compiler.hasErrors() is true; previously, different methods would sometimes call it & sometimes not. PiperOrigin-RevId: 721016838
1 parent ac6b08c commit fbd722a

File tree

1 file changed

+133
-210
lines changed

1 file changed

+133
-210
lines changed

src/com/google/javascript/jscomp/AbstractCommandLineRunner.java

+133-210
Original file line numberDiff line numberDiff line change
@@ -1251,9 +1251,7 @@ protected int doRun() throws IOException {
12511251
externs = null;
12521252
sources = null;
12531253

1254-
Result result;
1255-
// We won't want to process results for cases where compilation is only partially done.
1256-
boolean shouldProcessResults = true;
1254+
final Result result;
12571255
if (config.skipNormalOutputs) {
12581256
metricsRecorder.recordActionName("skip normal outputs");
12591257
// TODO(bradfordcsmith): Should we be ignoring possible init/initChunks() errors here?
@@ -1264,43 +1262,26 @@ protected int doRun() throws IOException {
12641262
// init() or initChunks() encountered an error.
12651263
compiler.generateReport();
12661264
result = compiler.getResult();
1267-
} else if (options.getInstrumentForCoverageOnly()) {
1268-
result = instrumentForCoverage(metricsRecorder);
1269-
} else if (config.shouldSaveAfterStage1()) {
1270-
result = performStage1andSave(config.getSaveCompilationStateToFilename(), metricsRecorder);
1271-
// Don't output any results, since compilation isn't done yet.
1272-
shouldProcessResults = false;
1273-
} else if (config.shouldRestoreTypedAstsPerformStage2AndSave()) {
1274-
result =
1275-
restoreTypedAstsPerformStage2AndSave(
1276-
config.getSaveCompilationStateToFilename(), metricsRecorder);
1277-
// Don't output any results, since compilation isn't done yet.
1278-
shouldProcessResults = false;
1279-
} else if (config.shouldRestoreTypedAstsPerformStages2And3()) {
1280-
result = restoreTypedAstsPerformStages2and3(metricsRecorder);
1281-
} else if (config.shouldRestoreAndPerformStage2AndSave()) {
1282-
result =
1283-
restoreAndPerformStage2AndSave(
1284-
config.getContinueSavedCompilationFileName(),
1285-
config.getSaveCompilationStateToFilename(),
1286-
metricsRecorder);
1287-
// Don't output any results, since compilation isn't done yet.
1288-
shouldProcessResults = false;
1289-
} else if (config.shouldRestoreAndPerformStages2And3()) {
1290-
result =
1291-
restoreAndPerformStages2and3(
1292-
config.getContinueSavedCompilationFileName(), metricsRecorder);
1293-
if (chunks != null) {
1294-
chunks = ImmutableList.copyOf(compiler.getChunks());
1295-
}
1296-
} else if (config.shouldRestoreAndPerformStage3()) {
1297-
result =
1298-
restoreAndPerformStage3(config.getContinueSavedCompilationFileName(), metricsRecorder);
1299-
if (chunks != null) {
1300-
chunks = ImmutableList.copyOf(compiler.getChunks());
1301-
}
13021265
} else {
1303-
result = performFullCompilation(metricsRecorder);
1266+
try {
1267+
// This is the common case - we're actually compiling something.
1268+
performCompilation(metricsRecorder);
1269+
result = compiler.getResult();
1270+
// If we're finished with compilation (i.e. we're not saving state), /and/ the compiler was
1271+
// restored from a previous state, then we need to re-initialize the set of chunks.
1272+
// TODO(lharker): figure out if this is still needed.
1273+
boolean refresh =
1274+
chunks != null
1275+
&& config.restoredCompilationStage != -1
1276+
&& config.saveAfterCompilationStage == -1;
1277+
if (refresh) {
1278+
chunks = ImmutableList.copyOf(compiler.getChunks());
1279+
}
1280+
} finally {
1281+
// Make sure we generate a report of errors and warnings even if the compiler throws an
1282+
// exception somewhere.
1283+
compiler.generateReport();
1284+
}
13041285
}
13051286

13061287
if (createCommonJsModules) {
@@ -1318,6 +1299,8 @@ protected int doRun() throws IOException {
13181299
}
13191300
}
13201301

1302+
// We won't want to process results for cases where compilation is only partially done.
1303+
boolean shouldProcessResults = config.getSaveCompilationStateToFilename() == null;
13211304
int exitStatus =
13221305
shouldProcessResults
13231306
? processResults(result, chunks, options)
@@ -1326,6 +1309,90 @@ protected int doRun() throws IOException {
13261309
return exitStatus;
13271310
}
13281311

1312+
private void performCompilation(CompileMetricsRecorderInterface metricsRecorder) {
1313+
// Parse, restore from a save file, or initialize from a TypedAST list.
1314+
initializeStateBeforeCompilation();
1315+
1316+
// Do the interesting work - checks, optimizations, etc.
1317+
runCompilerPasses(metricsRecorder);
1318+
1319+
// Save state unless there was an exception or error - we won't go on to the next stage if there
1320+
// was an error, and saving state itself might throw an exception if the compiler is in a bad
1321+
// state.
1322+
if (!compiler.hasErrors()) {
1323+
saveState();
1324+
}
1325+
// Perform post-compilation tasks even if compiler.hasErrors()
1326+
compiler.performPostCompilationTasks();
1327+
}
1328+
1329+
private void runCompilerPasses(CompileMetricsRecorderInterface metricsRecorder) {
1330+
boolean runStage1 = false;
1331+
boolean runStage2 = false;
1332+
boolean runStage3 = false;
1333+
boolean instrumentForCoverage = false;
1334+
final String actionMetricsName;
1335+
if (compiler.getOptions().getInstrumentForCoverageOnly()) {
1336+
actionMetricsName = "instrument for coverage";
1337+
instrumentForCoverage = true;
1338+
} else if (config.shouldSaveAfterStage1()) {
1339+
actionMetricsName = "stage 1";
1340+
runStage1 = true;
1341+
} else if (config.shouldRestoreTypedAstsPerformStage2AndSave()) {
1342+
actionMetricsName = "parse & optimize";
1343+
runStage2 = true;
1344+
} else if (config.shouldRestoreTypedAstsPerformStages2And3()) {
1345+
actionMetricsName = "skip-checks compile";
1346+
runStage2 = true;
1347+
runStage3 = true;
1348+
} else if (config.shouldRestoreAndPerformStage2AndSave()) {
1349+
actionMetricsName = "stage 2/3";
1350+
runStage2 = true;
1351+
} else if (config.shouldRestoreAndPerformStages2And3()) {
1352+
// From the outside this looks like the second stage of a 2-stage compile.
1353+
actionMetricsName = "stage 2/2";
1354+
runStage2 = true;
1355+
runStage3 = true;
1356+
} else if (config.shouldRestoreAndPerformStage3()) {
1357+
actionMetricsName = "stage 3/3";
1358+
runStage3 = true;
1359+
} else {
1360+
// This is the code path taken when "building" a library by just checking it for errors
1361+
// and generating an .ijs file and also when doing a full compilation.
1362+
actionMetricsName = compiler.getOptions().checksOnly ? "checks-only" : "full compile";
1363+
runStage1 = true;
1364+
runStage2 = true;
1365+
runStage3 = true;
1366+
}
1367+
1368+
metricsRecorder.recordActionName(actionMetricsName);
1369+
if (compiler.hasErrors()) {
1370+
return;
1371+
}
1372+
metricsRecorder.recordStartState(compiler);
1373+
if (runStage1) {
1374+
compiler.stage1Passes();
1375+
if (compiler.hasErrors()) {
1376+
return;
1377+
}
1378+
}
1379+
if (runStage2) {
1380+
compiler.stage2Passes(OptimizationPasses.ALL);
1381+
if (compiler.hasErrors()) {
1382+
return;
1383+
}
1384+
}
1385+
if (runStage3) {
1386+
compiler.stage3Passes();
1387+
if (compiler.hasErrors()) {
1388+
return;
1389+
}
1390+
}
1391+
if (instrumentForCoverage) {
1392+
compiler.instrumentForCoverage();
1393+
}
1394+
}
1395+
13291396
/**
13301397
* Child classes should override this if they want to actually record metrics about the
13311398
* compilation.
@@ -1334,30 +1401,6 @@ protected CompileMetricsRecorderInterface getCompileMetricsRecorder() {
13341401
return new DummyCompileMetricsRecorder();
13351402
}
13361403

1337-
private Result performStage1andSave(
1338-
String filename, CompileMetricsRecorderInterface metricsRecorder) {
1339-
metricsRecorder.recordActionName("stage 1");
1340-
try (BufferedOutputStream serializedOutputStream =
1341-
new BufferedOutputStream(new FileOutputStream(filename))) {
1342-
compiler.parseForCompilation();
1343-
if (!compiler.hasErrors()) {
1344-
metricsRecorder.recordStartState(compiler);
1345-
compiler.stage1Passes();
1346-
}
1347-
if (!compiler.hasErrors()) {
1348-
compiler.saveState(serializedOutputStream);
1349-
}
1350-
compiler.performPostCompilationTasks();
1351-
} catch (IOException e) {
1352-
compiler.report(JSError.make(COULD_NOT_SERIALIZE_AST, filename));
1353-
} finally {
1354-
// Make sure we generate a report of errors and warnings even if the compiler throws an
1355-
// exception somewhere.
1356-
compiler.generateReport();
1357-
}
1358-
return compiler.getResult();
1359-
}
1360-
13611404
private void initWithTypedAstFilesystem(
13621405
List<SourceFile> externs,
13631406
List<SourceFile> sources,
@@ -1381,166 +1424,46 @@ private void initChunksWithTypedAstFilesystem(
13811424
}
13821425
}
13831426

1384-
private Result restoreTypedAstsPerformStage2AndSave(
1385-
String outputFilename, CompileMetricsRecorderInterface metricsRecorder) {
1386-
metricsRecorder.recordActionName("parse & optimize");
1387-
try {
1388-
if (!compiler.hasErrors()) {
1389-
metricsRecorder.recordStartState(compiler);
1390-
compiler.stage2Passes(OptimizationPasses.ALL);
1391-
if (!compiler.hasErrors()) {
1392-
try (BufferedOutputStream serializedOutputStream =
1393-
new BufferedOutputStream(new FileOutputStream(outputFilename))) {
1394-
compiler.saveState(serializedOutputStream);
1395-
} catch (IOException e) {
1396-
compiler.report(JSError.make(COULD_NOT_SERIALIZE_AST, outputFilename));
1397-
}
1398-
compiler.performPostCompilationTasks();
1399-
}
1400-
}
1401-
} finally {
1402-
// Make sure we generate a report of errors and warnings even if the compiler throws an
1403-
// exception somewhere.
1404-
compiler.generateReport();
1405-
}
1406-
return compiler.getResult();
1407-
}
1408-
1409-
private Result restoreTypedAstsPerformStages2and3(
1410-
CompileMetricsRecorderInterface metricsRecorder) {
1411-
metricsRecorder.recordActionName("skip-checks compile");
1412-
try {
1413-
if (!compiler.hasErrors()) {
1414-
metricsRecorder.recordStartState(compiler);
1415-
compiler.stage2Passes(OptimizationPasses.ALL);
1416-
if (!compiler.hasErrors()) {
1417-
compiler.stage3Passes();
1418-
}
1419-
compiler.performPostCompilationTasks();
1420-
}
1421-
} finally {
1422-
// Make sure we generate a report of errors and warnings even if the compiler throws an
1423-
// exception somewhere.
1424-
compiler.generateReport();
1425-
}
1426-
return compiler.getResult();
1427+
/**
1428+
* Call at the beginning of compilation to initialize the compiler state.
1429+
*
1430+
* <p>Compiler state should be initialized no matter what the compilation stage is, but this
1431+
* method handles the different ways it might be initialized - whether from parsing actual JS
1432+
* files, from reading library-level TypedASTs, or from restoring a previous compilation state.
1433+
*/
1434+
private void initializeStateBeforeCompilation() {
1435+
if (config.restoredCompilationStage != -1) {
1436+
restoreState(config.getContinueSavedCompilationFileName());
1437+
} else if (config.typedAstListInputFilename != null) {
1438+
// we did this elsewhere
1439+
} else {
1440+
// parsing!
1441+
compiler.parseForCompilation();
14271442
}
1428-
1429-
private Result restoreAndPerformStage2AndSave(
1430-
String inputFilename,
1431-
String outputFilename,
1432-
CompileMetricsRecorderInterface metricsRecorder) {
1433-
metricsRecorder.recordActionName("stage 2/3");
1434-
try (BufferedInputStream serializedInputStream =
1435-
new BufferedInputStream(new FileInputStream(inputFilename))) {
1436-
compiler.restoreState(serializedInputStream);
1437-
if (!compiler.hasErrors()) {
1438-
metricsRecorder.recordStartState(compiler);
1439-
compiler.stage2Passes(OptimizationPasses.ALL);
1440-
if (!compiler.hasErrors()) {
1441-
try (BufferedOutputStream serializedOutputStream =
1442-
new BufferedOutputStream(new FileOutputStream(outputFilename))) {
1443-
compiler.saveState(serializedOutputStream);
1444-
} catch (IOException e) {
1445-
compiler.report(JSError.make(COULD_NOT_SERIALIZE_AST, outputFilename));
1446-
}
1447-
compiler.performPostCompilationTasks();
1448-
}
1449-
}
1450-
} catch (IOException | ClassNotFoundException e) {
1451-
compiler.report(JSError.make(COULD_NOT_DESERIALIZE_AST, inputFilename));
1452-
} finally {
1453-
// Make sure we generate a report of errors and warnings even if the compiler throws an
1454-
// exception somewhere.
1455-
compiler.generateReport();
1456-
}
1457-
return compiler.getResult();
14581443
}
14591444

1460-
private Result restoreAndPerformStages2and3(
1461-
String filename, CompileMetricsRecorderInterface metricsRecorder) {
1462-
// From the outside this looks like the second stage of a 2-stage compile.
1463-
metricsRecorder.recordActionName("stage 2/2");
1445+
private void restoreState(String filename) {
14641446
try (BufferedInputStream serializedInputStream =
14651447
new BufferedInputStream(new FileInputStream(filename))) {
14661448
compiler.restoreState(serializedInputStream);
1467-
if (!compiler.hasErrors()) {
1468-
metricsRecorder.recordStartState(compiler);
1469-
compiler.stage2Passes(OptimizationPasses.ALL);
1470-
if (!compiler.hasErrors()) {
1471-
compiler.stage3Passes();
1472-
}
1473-
}
1474-
compiler.performPostCompilationTasks();
14751449
} catch (IOException | ClassNotFoundException e) {
14761450
compiler.report(JSError.make(COULD_NOT_DESERIALIZE_AST, filename));
1477-
} finally {
1478-
// Make sure we generate a report of errors and warnings even if the compiler throws an
1479-
// exception somewhere.
1480-
compiler.generateReport();
14811451
}
1482-
return compiler.getResult();
14831452
}
14841453

1485-
private Result restoreAndPerformStage3(
1486-
String filename, CompileMetricsRecorderInterface metricsRecorder) {
1487-
metricsRecorder.recordActionName("stage 3/3");
1488-
try (BufferedInputStream serializedInputStream =
1489-
new BufferedInputStream(new FileInputStream(filename))) {
1490-
compiler.restoreState(serializedInputStream);
1491-
if (!compiler.hasErrors()) {
1492-
metricsRecorder.recordStartState(compiler);
1493-
compiler.stage3Passes();
1494-
}
1495-
compiler.performPostCompilationTasks();
1496-
} catch (IOException | ClassNotFoundException e) {
1497-
compiler.report(JSError.make(COULD_NOT_DESERIALIZE_AST, filename));
1498-
} finally {
1499-
// Make sure we generate a report of errors and warnings even if the compiler throws an
1500-
// exception somewhere.
1501-
compiler.generateReport();
1502-
}
1503-
return compiler.getResult();
1504-
}
1505-
1506-
private Result performFullCompilation(CompileMetricsRecorderInterface metricsRecorder) {
1507-
// This is the code path taken when "building" a library by just checking it for errors
1508-
// and generating an .ijs file and also when doing a full compilation.
1509-
metricsRecorder.recordActionName(
1510-
compiler.getOptions().checksOnly ? "checks-only" : "full compile");
1511-
try {
1512-
compiler.parseForCompilation();
1513-
if (!compiler.hasErrors()) {
1514-
metricsRecorder.recordStartState(compiler);
1515-
compiler.stage1Passes();
1516-
if (!compiler.hasErrors()) {
1517-
compiler.stage2Passes(OptimizationPasses.ALL);
1518-
if (!compiler.hasErrors()) {
1519-
compiler.stage3Passes();
1520-
}
1521-
}
1522-
compiler.performPostCompilationTasks();
1523-
}
1524-
} finally {
1525-
// Make sure we generate a report of errors and warnings even if the compiler throws an
1526-
// exception somewhere.
1527-
compiler.generateReport();
1454+
/** Call at the end of compilation to save the compiler state if applicable. */
1455+
private void saveState() {
1456+
if (config.getSaveCompilationStateToFilename() == null) {
1457+
// nothing to save to.
1458+
return;
15281459
}
1529-
return compiler.getResult();
1530-
}
1531-
1532-
private Result instrumentForCoverage(CompileMetricsRecorderInterface metricsRecorder) {
1533-
metricsRecorder.recordActionName("instrument for coverage");
1534-
try {
1535-
compiler.parseForCompilation();
1536-
if (!compiler.hasErrors()) {
1537-
metricsRecorder.recordStartState(compiler);
1538-
compiler.instrumentForCoverage();
1539-
}
1540-
} finally {
1541-
compiler.generateReport();
1460+
String filename = config.getSaveCompilationStateToFilename();
1461+
try (BufferedOutputStream serializedOutputStream =
1462+
new BufferedOutputStream(new FileOutputStream(filename))) {
1463+
compiler.saveState(serializedOutputStream);
1464+
} catch (IOException e) {
1465+
compiler.report(JSError.make(COULD_NOT_SERIALIZE_AST, filename));
15421466
}
1543-
return compiler.getResult();
15441467
}
15451468

15461469
/** Processes the results of the compile job, and returns an error code. */

0 commit comments

Comments
 (0)