OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Command line tool to run the checker on a Dart program. | 5 /// Command line tool to run the checker on a Dart program. |
6 library dev_compiler.devc; | 6 library dev_compiler.devc; |
7 | 7 |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 import 'dart:io'; | 10 import 'dart:io'; |
11 | 11 |
12 import 'package:analyzer/src/generated/error.dart' | |
13 show AnalysisError, ErrorSeverity, ErrorType; | |
14 import 'package:analyzer/src/generated/engine.dart' | 12 import 'package:analyzer/src/generated/engine.dart' |
15 show AnalysisContext, ChangeSet; | 13 show AnalysisContext, ChangeSet; |
| 14 import 'package:analyzer/src/generated/error.dart' |
| 15 show AnalysisError, AnalysisErrorListener, ErrorSeverity, ErrorType; |
16 import 'package:analyzer/src/generated/source.dart' show Source; | 16 import 'package:analyzer/src/generated/source.dart' show Source; |
17 import 'package:logging/logging.dart' show Level, Logger, LogRecord; | 17 import 'package:logging/logging.dart' show Level, Logger, LogRecord; |
18 import 'package:path/path.dart' as path; | 18 import 'package:path/path.dart' as path; |
19 import 'package:shelf/shelf.dart' as shelf; | 19 import 'package:shelf/shelf.dart' as shelf; |
20 import 'package:shelf/shelf_io.dart' as shelf; | 20 import 'package:shelf/shelf_io.dart' as shelf; |
21 import 'package:shelf_static/shelf_static.dart' as shelf_static; | 21 import 'package:shelf_static/shelf_static.dart' as shelf_static; |
22 | 22 |
23 import 'src/analysis_context.dart'; | 23 import 'src/analysis_context.dart'; |
24 import 'src/checker/checker.dart'; | 24 import 'src/checker/checker.dart'; |
25 import 'src/checker/rules.dart'; | 25 import 'src/checker/rules.dart'; |
(...skipping 21 matching lines...) Expand all Loading... |
47 AnalysisContext get context; | 47 AnalysisContext get context; |
48 TypeRules get rules; | 48 TypeRules get rules; |
49 Uri get entryPointUri; | 49 Uri get entryPointUri; |
50 } | 50 } |
51 | 51 |
52 /// Encapsulates the logic to do a one-off compilation or a partial compilation | 52 /// Encapsulates the logic to do a one-off compilation or a partial compilation |
53 /// when the compiler is run as a development server. | 53 /// when the compiler is run as a development server. |
54 class Compiler implements AbstractCompiler { | 54 class Compiler implements AbstractCompiler { |
55 final CompilerOptions options; | 55 final CompilerOptions options; |
56 final AnalysisContext context; | 56 final AnalysisContext context; |
57 final CompilerReporter _reporter; | 57 final AnalysisErrorListener _reporter; |
58 final TypeRules rules; | 58 final TypeRules rules; |
59 final CodeChecker _checker; | 59 final CodeChecker _checker; |
60 final SourceNode _entryNode; | 60 final SourceNode _entryNode; |
61 List<LibraryInfo> _libraries = <LibraryInfo>[]; | 61 List<LibraryInfo> _libraries = <LibraryInfo>[]; |
62 final _generators = <CodeGenerator>[]; | 62 final _generators = <CodeGenerator>[]; |
63 bool _hashing; | 63 bool _hashing; |
64 bool _failure = false; | 64 bool _failure = false; |
65 | 65 |
66 factory Compiler(CompilerOptions options, | 66 factory Compiler(CompilerOptions options, |
67 {AnalysisContext context, CompilerReporter reporter}) { | 67 {AnalysisContext context, AnalysisErrorListener reporter}) { |
68 var strongOpts = options.strongOptions; | 68 var strongOpts = options.strongOptions; |
69 var sourceOpts = options.sourceOptions; | 69 var sourceOpts = options.sourceOptions; |
70 if (context == null) { | 70 if (context == null) { |
71 context = createAnalysisContextWithSources(strongOpts, sourceOpts); | 71 context = createAnalysisContextWithSources(strongOpts, sourceOpts); |
72 } | 72 } |
73 | 73 |
74 if (reporter == null) { | 74 if (reporter == null) { |
75 reporter = options.dumpInfo | 75 reporter = options.dumpInfo |
76 ? new SummaryReporter(context, options.logLevel) | 76 ? new SummaryReporter(context, options.logLevel) |
77 : new LogReporter(context, useColors: options.useColors); | 77 : new LogReporter(context, useColors: options.useColors); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 assert(false); // should not get a build request on PartSourceNode | 117 assert(false); // should not get a build request on PartSourceNode |
118 } | 118 } |
119 | 119 |
120 // TODO(sigmund): don't always return true. Use summarization to better | 120 // TODO(sigmund): don't always return true. Use summarization to better |
121 // determine when rebuilding is needed. | 121 // determine when rebuilding is needed. |
122 return true; | 122 return true; |
123 } | 123 } |
124 | 124 |
125 void _buildHtmlFile(HtmlSourceNode node) { | 125 void _buildHtmlFile(HtmlSourceNode node) { |
126 if (outputDir == null) return; | 126 if (outputDir == null) return; |
127 var uri = node.source.uri; | |
128 _reporter.enterHtml(uri); | |
129 var output = generateEntryHtml(node, options); | 127 var output = generateEntryHtml(node, options); |
130 if (output == null) { | 128 if (output == null) { |
131 _failure = true; | 129 _failure = true; |
132 return; | 130 return; |
133 } | 131 } |
134 _reporter.leaveHtml(); | |
135 var filename = path.basename(node.uri.path); | 132 var filename = path.basename(node.uri.path); |
136 String outputFile = path.join(outputDir, filename); | 133 String outputFile = path.join(outputDir, filename); |
137 new File(outputFile).writeAsStringSync(output); | 134 new File(outputFile).writeAsStringSync(output); |
138 } | 135 } |
139 | 136 |
140 void _buildResourceFile(ResourceSourceNode node) { | 137 void _buildResourceFile(ResourceSourceNode node) { |
141 // ResourceSourceNodes files that just need to be copied over to the output | 138 // ResourceSourceNodes files that just need to be copied over to the output |
142 // location. These can be external dependencies or pieces of the | 139 // location. These can be external dependencies or pieces of the |
143 // dev_compiler runtime. | 140 // dev_compiler runtime. |
144 if (outputDir == null) return; | 141 if (outputDir == null) return; |
(...skipping 17 matching lines...) Expand all Loading... |
162 context.applyChanges(new ChangeSet()..changedSource(source)); | 159 context.applyChanges(new ChangeSet()..changedSource(source)); |
163 var entryUnit = context.resolveCompilationUnit2(source, source); | 160 var entryUnit = context.resolveCompilationUnit2(source, source); |
164 var lib = entryUnit.element.enclosingElement; | 161 var lib = entryUnit.element.enclosingElement; |
165 if (!options.checkSdk && lib.source.uri.scheme == 'dart') return; | 162 if (!options.checkSdk && lib.source.uri.scheme == 'dart') return; |
166 var current = node.info; | 163 var current = node.info; |
167 if (current != null) { | 164 if (current != null) { |
168 assert(current.library == lib); | 165 assert(current.library == lib); |
169 } else { | 166 } else { |
170 node.info = current = new LibraryInfo(lib, _isEntry(node)); | 167 node.info = current = new LibraryInfo(lib, _isEntry(node)); |
171 } | 168 } |
172 _reporter.enterLibrary(source.uri); | |
173 _libraries.add(current); | 169 _libraries.add(current); |
174 rules.currentLibraryInfo = current; | 170 rules.currentLibraryInfo = current; |
175 | 171 |
176 var resolvedParts = node.parts | 172 var resolvedParts = node.parts |
177 .map((p) => context.resolveCompilationUnit2(p.source, source)) | 173 .map((p) => context.resolveCompilationUnit2(p.source, source)) |
178 .toList(growable: false); | 174 .toList(growable: false); |
179 var libraryUnit = new LibraryUnit(entryUnit, resolvedParts); | 175 var libraryUnit = new LibraryUnit(entryUnit, resolvedParts); |
180 bool failureInLib = false; | 176 bool failureInLib = false; |
181 for (var unit in libraryUnit.libraryThenParts) { | 177 for (var unit in libraryUnit.libraryThenParts) { |
182 var unitSource = unit.element.source; | 178 var unitSource = unit.element.source; |
183 _reporter.enterCompilationUnit(unit); | |
184 // TODO(sigmund): integrate analyzer errors with static-info (issue #6). | |
185 failureInLib = logErrors(unitSource) || failureInLib; | 179 failureInLib = logErrors(unitSource) || failureInLib; |
186 _checker.visitCompilationUnit(unit); | 180 _checker.visitCompilationUnit(unit); |
187 if (_checker.failure) failureInLib = true; | 181 if (_checker.failure) failureInLib = true; |
188 _reporter.leaveCompilationUnit(); | |
189 } | 182 } |
190 if (failureInLib) { | 183 if (failureInLib) { |
191 _failure = true; | 184 _failure = true; |
192 if (!options.codegenOptions.forceCompile) return; | 185 if (!options.codegenOptions.forceCompile) return; |
193 } | 186 } |
194 | 187 |
195 for (var cg in _generators) { | 188 for (var cg in _generators) { |
196 var hash = cg.generateLibrary(libraryUnit, current); | 189 var hash = cg.generateLibrary(libraryUnit, current); |
197 if (_hashing) node.cachingHash = hash; | 190 if (_hashing) node.cachingHash = hash; |
198 } | 191 } |
199 _reporter.leaveLibrary(); | |
200 } | 192 } |
201 | 193 |
202 /// Log any errors encountered when resolving [source] and return whether any | 194 /// Log any errors encountered when resolving [source] and return whether any |
203 /// errors were found. | 195 /// errors were found. |
204 bool logErrors(Source source) { | 196 bool logErrors(Source source) { |
205 context.computeErrors(source); | 197 context.computeErrors(source); |
206 List<AnalysisError> errors = context.getErrors(source).errors; | 198 List<AnalysisError> errors = context.getErrors(source).errors; |
207 bool failure = false; | 199 bool failure = false; |
208 if (errors.isNotEmpty) { | 200 if (errors.isNotEmpty) { |
209 for (var error in errors) { | 201 for (var error in errors) { |
210 // Always skip TODOs. | 202 // Always skip TODOs. |
211 if (error.errorCode.type == ErrorType.TODO) continue; | 203 if (error.errorCode.type == ErrorType.TODO) continue; |
212 | 204 |
213 // Skip hints for now. In the future these could be turned on via flags. | 205 // Skip hints for now. In the future these could be turned on via flags. |
214 if (error.errorCode.errorSeverity.ordinal < | 206 if (error.errorCode.errorSeverity.ordinal < |
215 ErrorSeverity.WARNING.ordinal) { | 207 ErrorSeverity.WARNING.ordinal) { |
216 continue; | 208 continue; |
217 } | 209 } |
218 | 210 |
219 var message = new AnalyzerMessage.from(error); | 211 // All analyzer warnings or errors are errors for DDC. |
220 if (message.level == Level.SEVERE) failure = true; | 212 failure = true; |
221 _reporter.log(message); | 213 _reporter.onError(error); |
222 } | 214 } |
223 } | 215 } |
224 return failure; | 216 return failure; |
225 } | 217 } |
226 | 218 |
227 CheckerResults run() { | 219 CheckerResults run() { |
228 var clock = new Stopwatch()..start(); | 220 var clock = new Stopwatch()..start(); |
229 | 221 |
230 // TODO(sigmund): we are missing a couple failures here. The | 222 // TODO(sigmund): we are missing a couple failures here. The |
231 // dependency_graph now detects broken imports or unsupported features | 223 // dependency_graph now detects broken imports or unsupported features |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 // Note: the cache-control header should be enough, but this doesn't hurt | 329 // Note: the cache-control header should be enough, but this doesn't hurt |
338 // and can help renew the policy after it expires. | 330 // and can help renew the policy after it expires. |
339 headers['ETag'] = hash; | 331 headers['ETag'] = hash; |
340 } | 332 } |
341 return response.change(headers: headers); | 333 return response.change(headers: headers); |
342 }; | 334 }; |
343 } | 335 } |
344 | 336 |
345 final _log = new Logger('dev_compiler'); | 337 final _log = new Logger('dev_compiler'); |
346 final _earlyErrorResult = new CheckerResults(const [], null, true); | 338 final _earlyErrorResult = new CheckerResults(const [], null, true); |
OLD | NEW |