Index: lib/devc.dart |
diff --git a/lib/devc.dart b/lib/devc.dart |
index 826ab500813128144b7b93a69cadad43a9d75d8b..a187e71bd390c32d2c930322b0949a974a257c6b 100644 |
--- a/lib/devc.dart |
+++ b/lib/devc.dart |
@@ -9,7 +9,10 @@ import 'dart:async'; |
import 'dart:convert'; |
import 'dart:io'; |
-import 'package:analyzer/src/generated/engine.dart' show ChangeSet; |
+import 'package:analyzer/src/generated/error.dart' as analyzer; |
+import 'package:analyzer/src/generated/engine.dart' |
+ show AnalysisContext, ChangeSet; |
+import 'package:analyzer/src/generated/source.dart' show Source; |
import 'package:logging/logging.dart' show Level, Logger, LogRecord; |
import 'package:path/path.dart' as path; |
import 'package:shelf/shelf.dart' as shelf; |
@@ -25,7 +28,8 @@ import 'src/codegen/dart_codegen.dart'; |
import 'src/codegen/html_codegen.dart'; |
import 'src/codegen/js_codegen.dart'; |
import 'src/dependency_graph.dart'; |
-import 'src/info.dart' show LibraryInfo, CheckerResults, LibraryUnit; |
+import 'src/info.dart' |
+ show AnalyzerError, CheckerResults, LibraryInfo, LibraryUnit; |
import 'src/options.dart'; |
import 'src/report.dart'; |
import 'src/utils.dart'; |
@@ -39,19 +43,25 @@ StreamSubscription setupLogger(Level level, printFn) { |
}); |
} |
+abstract class AbstractCompiler { |
+ CompilerOptions get options; |
+ AnalysisContext get context; |
+ TypeRules get rules; |
+ Uri get entryPointUri; |
+} |
+ |
/// Encapsulates the logic to do a one-off compilation or a partial compilation |
/// when the compiler is run as a development server. |
-class Compiler { |
- final CompilerOptions _options; |
- final TypeResolver _resolver; |
+class Compiler implements AbstractCompiler { |
+ final CompilerOptions options; |
+ final AnalysisContext context; |
final CheckerReporter _reporter; |
- final TypeRules _rules; |
+ final TypeRules rules; |
final CodeChecker _checker; |
- final SourceGraph _graph; |
final SourceNode _entryNode; |
List<LibraryInfo> _libraries = <LibraryInfo>[]; |
- final List<CodeGenerator> _generators; |
- final bool _hashing; |
+ final _generators = <CodeGenerator>[]; |
+ bool _hashing; |
bool _failure = false; |
factory Compiler(CompilerOptions options, |
@@ -61,15 +71,15 @@ class Compiler { |
? new TypeResolver.fromMock(mockSdkSources, options) |
: new TypeResolver.fromDir(options.dartSdkPath, options); |
} |
+ var context = resolver.context; |
if (reporter == null) { |
reporter = options.dumpInfo |
- ? new SummaryReporter(options.logLevel) |
- : new LogReporter(options.useColors); |
+ ? new SummaryReporter(context, options.logLevel) |
+ : new LogReporter(context, useColors: options.useColors); |
} |
- var graph = new SourceGraph(resolver.context, reporter, options); |
- var rules = |
- new RestrictedRules(resolver.context.typeProvider, options: options); |
+ var graph = new SourceGraph(context, reporter, options); |
+ var rules = new RestrictedRules(context.typeProvider, options: options); |
var checker = new CodeChecker(rules, reporter, options); |
var inputFile = options.entryPointFile; |
@@ -80,26 +90,26 @@ class Compiler { |
? ResolverOptions.implicitHtmlFile |
: inputFile)); |
var entryNode = graph.nodeFromUri(inputUri); |
- var outputDir = options.outputDir; |
- var generators = <CodeGenerator>[]; |
+ |
+ return new Compiler._( |
+ options, context, reporter, rules, checker, entryNode); |
+ } |
+ |
+ Compiler._(this.options, this.context, this._reporter, this.rules, |
+ this._checker, this._entryNode) { |
if (options.dumpSrcDir != null) { |
- generators.add(new EmptyDartGenerator( |
- options.dumpSrcDir, entryNode.uri, rules, options)); |
+ _generators.add(new EmptyDartGenerator(this)); |
} |
- if (outputDir != null) { |
- generators.add(options.outputDart |
- ? new DartGenerator(outputDir, entryNode.uri, rules, options) |
- : new JSGenerator(outputDir, entryNode.uri, rules, options)); |
+ if (options.outputDir != null) { |
+ _generators.add( |
+ options.outputDart ? new DartGenerator(this) : new JSGenerator(this)); |
} |
- return new Compiler._(options, resolver, reporter, rules, checker, graph, |
- entryNode, generators, |
- // TODO(sigmund): refactor to support hashing of the dart output? |
- options.enableHashing && generators.length == 1 && !options.outputDart); |
+ // TODO(sigmund): refactor to support hashing of the dart output? |
+ _hashing = |
+ options.enableHashing && _generators.length == 1 && !options.outputDart; |
} |
- Compiler._(this._options, this._resolver, this._reporter, this._rules, |
- this._checker, this._graph, this._entryNode, this._generators, |
- this._hashing); |
+ Uri get entryPointUri => _entryNode.uri; |
bool _buildSource(SourceNode node) { |
if (node is HtmlSourceNode) { |
@@ -118,30 +128,30 @@ class Compiler { |
} |
void _buildHtmlFile(HtmlSourceNode node) { |
- if (_options.outputDir == null) return; |
+ if (options.outputDir == null) return; |
var uri = node.source.uri; |
_reporter.enterHtml(uri); |
- var output = generateEntryHtml(node, _options); |
+ var output = generateEntryHtml(node, options); |
if (output == null) { |
_failure = true; |
return; |
} |
_reporter.leaveHtml(); |
var filename = path.basename(node.uri.path); |
- String outputFile = path.join(_options.outputDir, filename); |
+ String outputFile = path.join(options.outputDir, filename); |
new File(outputFile).writeAsStringSync(output); |
- if (_options.outputDart) return; |
+ if (options.outputDart) return; |
} |
void _buildResourceFile(ResourceSourceNode node) { |
// ResourceSourceNodes files that just need to be copied over to the output |
// location. These can be external dependencies or pieces of the |
// dev_compiler runtime. |
- if (_options.outputDir == null || _options.outputDart) return; |
+ if (options.outputDir == null || options.outputDart) return; |
var filepath = resourceOutputPath(node.uri, _entryNode.uri); |
assert(filepath != null); |
- filepath = path.join(_options.outputDir, filepath); |
+ filepath = path.join(options.outputDir, filepath); |
var dir = path.dirname(filepath); |
new Directory(dir).createSync(recursive: true); |
new File.fromUri(node.source.uri).copySync(filepath); |
@@ -156,10 +166,10 @@ class Compiler { |
void _buildDartLibrary(DartSourceNode node) { |
var source = node.source; |
// TODO(sigmund): find out from analyzer team if there is a better way |
- _resolver.context.applyChanges(new ChangeSet()..changedSource(source)); |
- var entryUnit = _resolver.context.resolveCompilationUnit2(source, source); |
+ context.applyChanges(new ChangeSet()..changedSource(source)); |
+ var entryUnit = context.resolveCompilationUnit2(source, source); |
var lib = entryUnit.element.enclosingElement; |
- if (!_options.checkSdk && lib.isInSdk) return; |
+ if (!options.checkSdk && lib.isInSdk) return; |
var current = node.info; |
if (current != null) { |
assert(current.library == lib); |
@@ -168,25 +178,25 @@ class Compiler { |
} |
_reporter.enterLibrary(source.uri); |
_libraries.add(current); |
- _rules.currentLibraryInfo = current; |
+ rules.currentLibraryInfo = current; |
var resolvedParts = node.parts |
- .map((p) => _resolver.context.resolveCompilationUnit2(p.source, source)) |
+ .map((p) => context.resolveCompilationUnit2(p.source, source)) |
.toList(growable: false); |
var libraryUnit = new LibraryUnit(entryUnit, resolvedParts); |
bool failureInLib = false; |
for (var unit in libraryUnit.libraryThenParts) { |
var unitSource = unit.element.source; |
- _reporter.enterSource(unitSource); |
+ _reporter.enterCompilationUnit(unit); |
// TODO(sigmund): integrate analyzer errors with static-info (issue #6). |
- failureInLib = _resolver.logErrors(unitSource, _reporter) || failureInLib; |
+ failureInLib = logErrors(unitSource) || failureInLib; |
_checker.visitCompilationUnit(unit); |
if (_checker.failure) failureInLib = true; |
- _reporter.leaveSource(); |
+ _reporter.leaveCompilationUnit(); |
} |
if (failureInLib) { |
_failure = true; |
- if (!_options.forceCompile) return; |
+ if (!options.forceCompile) return; |
} |
for (var cg in _generators) { |
@@ -196,6 +206,21 @@ class Compiler { |
_reporter.leaveLibrary(); |
} |
+ /// Log any errors encountered when resolving [source] and return whether any |
+ /// errors were found. |
+ bool logErrors(Source source) { |
+ List<analyzer.AnalysisError> errors = context.getErrors(source).errors; |
+ bool failure = false; |
+ if (errors.isNotEmpty) { |
+ for (var error in errors) { |
+ var message = new AnalyzerError.from(error); |
+ if (message.level == Level.SEVERE) failure = true; |
+ _reporter.log(message); |
+ } |
+ } |
+ return failure; |
+ } |
+ |
CheckerResults run() { |
var clock = new Stopwatch()..start(); |
@@ -204,13 +229,13 @@ class Compiler { |
// like more than one script tag (see .severe messages in |
// dependency_graph.dart). Such failures should be reported back |
// here so we can mark failure=true in the CheckerResutls. |
- rebuild(_entryNode, _graph, _buildSource); |
+ rebuild(_entryNode, _buildSource); |
_dumpInfoIfRequested(); |
clock.stop(); |
var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); |
_log.fine('Compiled ${_libraries.length} libraries in ${time} s\n'); |
return new CheckerResults( |
- _libraries, _rules, _failure || _options.forceCompile); |
+ _libraries, rules, _failure || options.forceCompile); |
} |
void _runAgain() { |
@@ -219,7 +244,7 @@ class Compiler { |
int changed = 0; |
// TODO(sigmund): propagate failures here (see TODO in run). |
- rebuild(_entryNode, _graph, (n) { |
+ rebuild(_entryNode, (n) { |
changed++; |
return _buildSource(n); |
}); |
@@ -230,12 +255,12 @@ class Compiler { |
} |
_dumpInfoIfRequested() { |
- if (!_options.dumpInfo || _reporter is! SummaryReporter) return; |
+ if (!options.dumpInfo || _reporter is! SummaryReporter) return; |
var result = (_reporter as SummaryReporter).result; |
- if (!_options.serverMode) print(summaryToString(result)); |
- var filepath = _options.serverMode |
- ? path.join(_options.outputDir, 'messages.json') |
- : _options.dumpInfoFile; |
+ if (!options.serverMode) print(summaryToString(result)); |
+ var filepath = options.serverMode |
+ ? path.join(options.outputDir, 'messages.json') |
+ : options.dumpInfoFile; |
if (filepath == null) return; |
new File(filepath).writeAsStringSync(JSON.encode(result.toJsonMap())); |
} |
@@ -272,7 +297,7 @@ class CompilerServer { |
CompilerServer._( |
Compiler compiler, this.outDir, this.host, this.port, String entryPath) |
: this.compiler = compiler, |
- this._entryPath = compiler._options.useImplicitHtml |
+ this._entryPath = compiler.options.useImplicitHtml |
? ResolverOptions.implicitHtmlFile |
: entryPath; |