Files
sdk/pkg/dev_compiler/lib/devc.dart
T

106 lines
3.8 KiB
Dart

/// Command line tool to run the checker on a Dart program.
library ddc.devc;
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:logging/logging.dart' show Level, Logger, LogRecord;
import 'package:path/path.dart' as path;
import 'src/checker/resolver.dart';
import 'src/checker/checker.dart';
import 'src/checker/rules.dart';
import 'src/codegen/code_generator.dart' show CodeGenerator;
import 'src/codegen/dart_codegen.dart';
import 'src/codegen/js_codegen.dart';
import 'src/report.dart';
import 'src/info.dart' show LibraryInfo, CheckerResults;
import 'src/utils.dart' show reachableSources, partsOf;
/// Sets up the type checker logger to print a span that highlights error
/// messages.
StreamSubscription setupLogger(Level level, printFn) {
Logger.root.level = level;
return Logger.root.onRecord.listen((LogRecord rec) {
printFn('${rec.level.name.toLowerCase()}: ${rec.message}');
});
}
/// Compiles [inputFile] writing output as specified by the arguments.
/// [dumpInfoFile] will only be used if [dumpInfo] is true.
CheckerResults compile(String inputFile, TypeResolver resolver,
{CheckerReporter reporter, bool checkSdk: false, bool formatOutput: false,
bool outputDart: false, String outputDir, bool dumpInfo: false,
String dumpInfoFile, String dumpSrcTo: null, bool forceCompile: false,
bool useColors: true, bool covariantGenerics: true,
bool relaxedCasts: true}) {
var uri = new Uri.file(path.absolute(inputFile));
if (reporter == null) {
reporter = dumpInfo ? new SummaryReporter() : new LogReporter(useColors);
}
var libraries = <LibraryInfo>[];
var rules = new RestrictedRules(resolver.context.typeProvider, reporter,
covariantGenerics: covariantGenerics, relaxedCasts: relaxedCasts);
var codeChecker = new CodeChecker(rules, reporter);
var generators = <CodeGenerator>[];
if (dumpSrcTo != null) {
generators.add(
new EmptyDartGenerator(dumpSrcTo, uri, libraries, rules, formatOutput));
}
if (outputDir != null) {
var cg = outputDart
? new DartGenerator(outputDir, uri, libraries, rules, formatOutput)
: new JSGenerator(outputDir, uri, libraries, rules);
generators.add(cg);
}
bool failure = false;
var rootSource = resolver.findSource(uri);
// TODO(sigmund): switch to use synchronous codegen?
for (var source in reachableSources(rootSource, resolver.context)) {
var entryUnit = resolver.context.resolveCompilationUnit2(source, source);
var lib = entryUnit.element.enclosingElement;
if (!checkSdk && lib.isInSdk) continue;
var current = new LibraryInfo(lib);
reporter.enterLibrary(current);
libraries.add(current);
rules.currentLibraryInfo = current;
var units = [entryUnit]
..addAll(partsOf(entryUnit, resolver.context)
.map((p) => resolver.context.resolveCompilationUnit2(p, source)));
bool failureInLib = false;
for (var unit in units) {
var unitSource = unit.element.source;
reporter.enterSource(unitSource);
// TODO(sigmund): integrate analyzer errors with static-info (issue #6).
failureInLib = resolver.logErrors(unitSource, reporter) || failureInLib;
unit.visitChildren(codeChecker);
if (codeChecker.failure) failureInLib = true;
reporter.leaveSource();
}
reporter.leaveLibrary();
if (failureInLib) {
failure = true;
if (!forceCompile) continue;
}
for (var cg in generators) {
cg.generateLibrary(units, current);
}
}
if (dumpInfo && reporter is SummaryReporter) {
print(summaryToString(reporter.result));
if (dumpInfoFile != null) {
new File(dumpInfoFile)
.writeAsStringSync(JSON.encode(reporter.result.toJsonMap()));
}
}
return new CheckerResults(libraries, rules, failure || forceCompile);
}
final _log = new Logger('ddc');