@@ -9,7 +9,10 @@ import 'dart:async';
9
9
import 'dart:convert' ;
10
10
import 'dart:io' ;
11
11
12
- import 'package:analyzer/src/generated/engine.dart' show ChangeSet;
12
+ import 'package:analyzer/src/generated/error.dart' as analyzer;
13
+ import 'package:analyzer/src/generated/engine.dart'
14
+ show AnalysisContext, ChangeSet;
15
+ import 'package:analyzer/src/generated/source.dart' show Source;
13
16
import 'package:logging/logging.dart' show Level, Logger, LogRecord;
14
17
import 'package:path/path.dart' as path;
15
18
import 'package:shelf/shelf.dart' as shelf;
@@ -25,7 +28,8 @@ import 'src/codegen/dart_codegen.dart';
25
28
import 'src/codegen/html_codegen.dart' ;
26
29
import 'src/codegen/js_codegen.dart' ;
27
30
import 'src/dependency_graph.dart' ;
28
- import 'src/info.dart' show LibraryInfo, CheckerResults, LibraryUnit;
31
+ import 'src/info.dart'
32
+ show AnalyzerError, CheckerResults, LibraryInfo, LibraryUnit;
29
33
import 'src/options.dart' ;
30
34
import 'src/report.dart' ;
31
35
import 'src/utils.dart' ;
@@ -39,19 +43,25 @@ StreamSubscription setupLogger(Level level, printFn) {
39
43
});
40
44
}
41
45
46
+ abstract class AbstractCompiler {
47
+ CompilerOptions get options;
48
+ AnalysisContext get context;
49
+ TypeRules get rules;
50
+ Uri get entryPointUri;
51
+ }
52
+
42
53
/// Encapsulates the logic to do a one-off compilation or a partial compilation
43
54
/// when the compiler is run as a development server.
44
- class Compiler {
45
- final CompilerOptions _options ;
46
- final TypeResolver _resolver ;
55
+ class Compiler implements AbstractCompiler {
56
+ final CompilerOptions options ;
57
+ final AnalysisContext context ;
47
58
final CheckerReporter _reporter;
48
- final TypeRules _rules ;
59
+ final TypeRules rules ;
49
60
final CodeChecker _checker;
50
- final SourceGraph _graph;
51
61
final SourceNode _entryNode;
52
62
List <LibraryInfo > _libraries = < LibraryInfo > [];
53
- final List <CodeGenerator > _generators ;
54
- final bool _hashing;
63
+ final _generators = < CodeGenerator > [] ;
64
+ bool _hashing;
55
65
bool _failure = false ;
56
66
57
67
factory Compiler (CompilerOptions options,
@@ -61,15 +71,15 @@ class Compiler {
61
71
? new TypeResolver .fromMock (mockSdkSources, options)
62
72
: new TypeResolver .fromDir (options.dartSdkPath, options);
63
73
}
74
+ var context = resolver.context;
64
75
65
76
if (reporter == null ) {
66
77
reporter = options.dumpInfo
67
- ? new SummaryReporter (options.logLevel)
68
- : new LogReporter (options.useColors);
78
+ ? new SummaryReporter (context, options.logLevel)
79
+ : new LogReporter (context, useColors : options.useColors);
69
80
}
70
- var graph = new SourceGraph (resolver.context, reporter, options);
71
- var rules =
72
- new RestrictedRules (resolver.context.typeProvider, options: options);
81
+ var graph = new SourceGraph (context, reporter, options);
82
+ var rules = new RestrictedRules (context.typeProvider, options: options);
73
83
var checker = new CodeChecker (rules, reporter, options);
74
84
75
85
var inputFile = options.entryPointFile;
@@ -80,26 +90,26 @@ class Compiler {
80
90
? ResolverOptions .implicitHtmlFile
81
91
: inputFile));
82
92
var entryNode = graph.nodeFromUri (inputUri);
83
- var outputDir = options.outputDir;
84
- var generators = < CodeGenerator > [];
93
+
94
+ return new Compiler ._(
95
+ options, context, reporter, rules, checker, entryNode);
96
+ }
97
+
98
+ Compiler ._(this .options, this .context, this ._reporter, this .rules,
99
+ this ._checker, this ._entryNode) {
85
100
if (options.dumpSrcDir != null ) {
86
- generators.add (new EmptyDartGenerator (
87
- options.dumpSrcDir, entryNode.uri, rules, options));
101
+ _generators.add (new EmptyDartGenerator (this ));
88
102
}
89
- if (outputDir != null ) {
90
- generators.add (options.outputDart
91
- ? new DartGenerator (outputDir, entryNode.uri, rules, options)
92
- : new JSGenerator (outputDir, entryNode.uri, rules, options));
103
+ if (options.outputDir != null ) {
104
+ _generators.add (
105
+ options.outputDart ? new DartGenerator (this ) : new JSGenerator (this ));
93
106
}
94
- return new Compiler ._(options, resolver, reporter, rules, checker, graph,
95
- entryNode, generators,
96
- // TODO(sigmund): refactor to support hashing of the dart output?
97
- options.enableHashing && generators.length == 1 && ! options.outputDart);
107
+ // TODO(sigmund): refactor to support hashing of the dart output?
108
+ _hashing =
109
+ options.enableHashing && _generators.length == 1 && ! options.outputDart;
98
110
}
99
111
100
- Compiler ._(this ._options, this ._resolver, this ._reporter, this ._rules,
101
- this ._checker, this ._graph, this ._entryNode, this ._generators,
102
- this ._hashing);
112
+ Uri get entryPointUri => _entryNode.uri;
103
113
104
114
bool _buildSource (SourceNode node) {
105
115
if (node is HtmlSourceNode ) {
@@ -118,30 +128,30 @@ class Compiler {
118
128
}
119
129
120
130
void _buildHtmlFile (HtmlSourceNode node) {
121
- if (_options .outputDir == null ) return ;
131
+ if (options .outputDir == null ) return ;
122
132
var uri = node.source.uri;
123
133
_reporter.enterHtml (uri);
124
- var output = generateEntryHtml (node, _options );
134
+ var output = generateEntryHtml (node, options );
125
135
if (output == null ) {
126
136
_failure = true ;
127
137
return ;
128
138
}
129
139
_reporter.leaveHtml ();
130
140
var filename = path.basename (node.uri.path);
131
- String outputFile = path.join (_options .outputDir, filename);
141
+ String outputFile = path.join (options .outputDir, filename);
132
142
new File (outputFile).writeAsStringSync (output);
133
143
134
- if (_options .outputDart) return ;
144
+ if (options .outputDart) return ;
135
145
}
136
146
137
147
void _buildResourceFile (ResourceSourceNode node) {
138
148
// ResourceSourceNodes files that just need to be copied over to the output
139
149
// location. These can be external dependencies or pieces of the
140
150
// dev_compiler runtime.
141
- if (_options .outputDir == null || _options .outputDart) return ;
151
+ if (options .outputDir == null || options .outputDart) return ;
142
152
var filepath = resourceOutputPath (node.uri, _entryNode.uri);
143
153
assert (filepath != null );
144
- filepath = path.join (_options .outputDir, filepath);
154
+ filepath = path.join (options .outputDir, filepath);
145
155
var dir = path.dirname (filepath);
146
156
new Directory (dir).createSync (recursive: true );
147
157
new File .fromUri (node.source.uri).copySync (filepath);
@@ -156,10 +166,10 @@ class Compiler {
156
166
void _buildDartLibrary (DartSourceNode node) {
157
167
var source = node.source;
158
168
// TODO(sigmund): find out from analyzer team if there is a better way
159
- _resolver. context.applyChanges (new ChangeSet ()..changedSource (source));
160
- var entryUnit = _resolver. context.resolveCompilationUnit2 (source, source);
169
+ context.applyChanges (new ChangeSet ()..changedSource (source));
170
+ var entryUnit = context.resolveCompilationUnit2 (source, source);
161
171
var lib = entryUnit.element.enclosingElement;
162
- if (! _options .checkSdk && lib.isInSdk) return ;
172
+ if (! options .checkSdk && lib.isInSdk) return ;
163
173
var current = node.info;
164
174
if (current != null ) {
165
175
assert (current.library == lib);
@@ -168,25 +178,25 @@ class Compiler {
168
178
}
169
179
_reporter.enterLibrary (source.uri);
170
180
_libraries.add (current);
171
- _rules .currentLibraryInfo = current;
181
+ rules .currentLibraryInfo = current;
172
182
173
183
var resolvedParts = node.parts
174
- .map ((p) => _resolver. context.resolveCompilationUnit2 (p.source, source))
184
+ .map ((p) => context.resolveCompilationUnit2 (p.source, source))
175
185
.toList (growable: false );
176
186
var libraryUnit = new LibraryUnit (entryUnit, resolvedParts);
177
187
bool failureInLib = false ;
178
188
for (var unit in libraryUnit.libraryThenParts) {
179
189
var unitSource = unit.element.source;
180
- _reporter.enterSource (unitSource );
190
+ _reporter.enterCompilationUnit (unit );
181
191
// TODO(sigmund): integrate analyzer errors with static-info (issue #6).
182
- failureInLib = _resolver. logErrors (unitSource, _reporter ) || failureInLib;
192
+ failureInLib = logErrors (unitSource) || failureInLib;
183
193
_checker.visitCompilationUnit (unit);
184
194
if (_checker.failure) failureInLib = true ;
185
- _reporter.leaveSource ();
195
+ _reporter.leaveCompilationUnit ();
186
196
}
187
197
if (failureInLib) {
188
198
_failure = true ;
189
- if (! _options .forceCompile) return ;
199
+ if (! options .forceCompile) return ;
190
200
}
191
201
192
202
for (var cg in _generators) {
@@ -196,6 +206,21 @@ class Compiler {
196
206
_reporter.leaveLibrary ();
197
207
}
198
208
209
+ /// Log any errors encountered when resolving [source] and return whether any
210
+ /// errors were found.
211
+ bool logErrors (Source source) {
212
+ List <analyzer.AnalysisError > errors = context.getErrors (source).errors;
213
+ bool failure = false ;
214
+ if (errors.isNotEmpty) {
215
+ for (var error in errors) {
216
+ var message = new AnalyzerError .from (error);
217
+ if (message.level == Level .SEVERE ) failure = true ;
218
+ _reporter.log (message);
219
+ }
220
+ }
221
+ return failure;
222
+ }
223
+
199
224
CheckerResults run () {
200
225
var clock = new Stopwatch ()..start ();
201
226
@@ -204,13 +229,13 @@ class Compiler {
204
229
// like more than one script tag (see .severe messages in
205
230
// dependency_graph.dart). Such failures should be reported back
206
231
// here so we can mark failure=true in the CheckerResutls.
207
- rebuild (_entryNode, _graph, _buildSource);
232
+ rebuild (_entryNode, _buildSource);
208
233
_dumpInfoIfRequested ();
209
234
clock.stop ();
210
235
var time = (clock.elapsedMilliseconds / 1000 ).toStringAsFixed (2 );
211
236
_log.fine ('Compiled ${_libraries .length } libraries in ${time } s\n ' );
212
237
return new CheckerResults (
213
- _libraries, _rules , _failure || _options .forceCompile);
238
+ _libraries, rules , _failure || options .forceCompile);
214
239
}
215
240
216
241
void _runAgain () {
@@ -219,7 +244,7 @@ class Compiler {
219
244
int changed = 0 ;
220
245
221
246
// TODO(sigmund): propagate failures here (see TODO in run).
222
- rebuild (_entryNode, _graph, (n) {
247
+ rebuild (_entryNode, (n) {
223
248
changed++ ;
224
249
return _buildSource (n);
225
250
});
@@ -230,12 +255,12 @@ class Compiler {
230
255
}
231
256
232
257
_dumpInfoIfRequested () {
233
- if (! _options .dumpInfo || _reporter is ! SummaryReporter ) return ;
258
+ if (! options .dumpInfo || _reporter is ! SummaryReporter ) return ;
234
259
var result = (_reporter as SummaryReporter ).result;
235
- if (! _options .serverMode) print (summaryToString (result));
236
- var filepath = _options .serverMode
237
- ? path.join (_options .outputDir, 'messages.json' )
238
- : _options .dumpInfoFile;
260
+ if (! options .serverMode) print (summaryToString (result));
261
+ var filepath = options .serverMode
262
+ ? path.join (options .outputDir, 'messages.json' )
263
+ : options .dumpInfoFile;
239
264
if (filepath == null ) return ;
240
265
new File (filepath).writeAsStringSync (JSON .encode (result.toJsonMap ()));
241
266
}
@@ -272,7 +297,7 @@ class CompilerServer {
272
297
CompilerServer ._(
273
298
Compiler compiler, this .outDir, this .host, this .port, String entryPath)
274
299
: this .compiler = compiler,
275
- this ._entryPath = compiler._options .useImplicitHtml
300
+ this ._entryPath = compiler.options .useImplicitHtml
276
301
? ResolverOptions .implicitHtmlFile
277
302
: entryPath;
278
303
0 commit comments