| 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'; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 resolver = options.useMockSdk | 58 resolver = options.useMockSdk |
| 59 ? new TypeResolver.fromMock(mockSdkSources, options) | 59 ? new TypeResolver.fromMock(mockSdkSources, options) |
| 60 : new TypeResolver.fromDir(options.dartSdkPath, options); | 60 : new TypeResolver.fromDir(options.dartSdkPath, options); |
| 61 } | 61 } |
| 62 | 62 |
| 63 if (reporter == null) { | 63 if (reporter == null) { |
| 64 reporter = options.dumpInfo | 64 reporter = options.dumpInfo |
| 65 ? new SummaryReporter() | 65 ? new SummaryReporter() |
| 66 : new LogReporter(options.useColors); | 66 : new LogReporter(options.useColors); |
| 67 } | 67 } |
| 68 var graph = new SourceGraph(resolver.context, options); | 68 var graph = new SourceGraph(resolver.context, reporter); |
| 69 var rules = new RestrictedRules(resolver.context.typeProvider, reporter, | 69 var rules = new RestrictedRules(resolver.context.typeProvider, reporter, |
| 70 options: options); | 70 options: options); |
| 71 var checker = new CodeChecker(rules, reporter, options); | 71 var checker = new CodeChecker(rules, reporter, options); |
| 72 var inputFile = options.entryPointFile; | 72 var inputFile = options.entryPointFile; |
| 73 var uri = inputFile.startsWith('dart:') || inputFile.startsWith('package:') | 73 var uri = inputFile.startsWith('dart:') || inputFile.startsWith('package:') |
| 74 ? Uri.parse(inputFile) | 74 ? Uri.parse(inputFile) |
| 75 : new Uri.file(path.absolute(inputFile)); | 75 : new Uri.file(path.absolute(inputFile)); |
| 76 var entryNode = graph.nodeFromUri(uri); | 76 var entryNode = graph.nodeFromUri(uri); |
| 77 | 77 |
| 78 var outputDir = options.outputDir; | 78 var outputDir = options.outputDir; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 91 } | 91 } |
| 92 | 92 |
| 93 Compiler._(this._options, this._resolver, this._reporter, this._rules, | 93 Compiler._(this._options, this._resolver, this._reporter, this._rules, |
| 94 this._checker, this._graph, this._entryNode, this._generators); | 94 this._checker, this._graph, this._entryNode, this._generators); |
| 95 | 95 |
| 96 bool _buildSource(SourceNode node) { | 96 bool _buildSource(SourceNode node) { |
| 97 if (node is HtmlSourceNode) { | 97 if (node is HtmlSourceNode) { |
| 98 _buildHtmlFile(node); | 98 _buildHtmlFile(node); |
| 99 } else if (node is DartSourceNode) { | 99 } else if (node is DartSourceNode) { |
| 100 _buildDartLibrary(node); | 100 _buildDartLibrary(node); |
| 101 } else if (node is JavaScriptSourceNode) { | 101 } else if (node is ResourceSourceNode) { |
| 102 _buildJavaScriptFile(node); | 102 _buildResourceFile(node); |
| 103 } else { | 103 } else { |
| 104 assert(false); // should not get a build request on PartSourceNode | 104 assert(false); // should not get a build request on PartSourceNode |
| 105 } | 105 } |
| 106 | 106 |
| 107 // TODO(sigmund): don't always return true. Use summarization to better | 107 // TODO(sigmund): don't always return true. Use summarization to better |
| 108 // determine when rebuilding is needed. | 108 // determine when rebuilding is needed. |
| 109 return true; | 109 return true; |
| 110 } | 110 } |
| 111 | 111 |
| 112 void _buildHtmlFile(HtmlSourceNode node) { | 112 void _buildHtmlFile(HtmlSourceNode node) { |
| 113 if (_options.outputDir == null) return; | 113 if (_options.outputDir == null) return; |
| 114 var uri = node.source.uri; |
| 115 _reporter.enterHtml(uri); |
| 114 var output = generateEntryHtml(node, _options); | 116 var output = generateEntryHtml(node, _options); |
| 115 if (output == null) { | 117 if (output == null) { |
| 116 _failure = true; | 118 _failure = true; |
| 117 return; | 119 return; |
| 118 } | 120 } |
| 121 _reporter.leaveHtml(); |
| 119 var filename = path.basename(node.uri.path); | 122 var filename = path.basename(node.uri.path); |
| 120 String outputFile = path.join(_options.outputDir, filename); | 123 String outputFile = path.join(_options.outputDir, filename); |
| 121 new File(outputFile).writeAsStringSync(output); | 124 new File(outputFile).writeAsStringSync(output); |
| 122 | 125 |
| 123 if (_options.outputDart) return; | 126 if (_options.outputDart) return; |
| 124 } | 127 } |
| 125 | 128 |
| 126 void _buildJavaScriptFile(JavaScriptSourceNode node) { | 129 void _buildResourceFile(ResourceSourceNode node) { |
| 127 // JavaScriptSourceNodes are pieces of the dev_compiler runtime which are | 130 // ResourceSourceNodes are pieces of the dev_compiler runtime which are |
| 128 // dependencies added for js codegen. | 131 // dependencies added for js codegen. |
| 129 if (_options.outputDir == null || _options.outputDart) return; | 132 if (_options.outputDir == null || _options.outputDart) return; |
| 130 assert(node.uri.scheme == 'package'); | 133 assert(node.uri.scheme == 'package'); |
| 131 var filepath = path.join(_options.outputDir, node.uri.path); | 134 var filepath = path.join(_options.outputDir, node.uri.path); |
| 132 var dir = path.dirname(filepath); | 135 var dir = path.dirname(filepath); |
| 133 new Directory(dir).createSync(recursive: true); | 136 new Directory(dir).createSync(recursive: true); |
| 134 new File(filepath).writeAsStringSync(node.source.contents.data); | 137 new File(filepath).writeAsStringSync(node.source.contents.data); |
| 135 } | 138 } |
| 136 | 139 |
| 137 bool _isEntry(DartSourceNode node) { | 140 bool _isEntry(DartSourceNode node) { |
| 138 if (_entryNode is DartSourceNode) return _entryNode == node; | 141 if (_entryNode is DartSourceNode) return _entryNode == node; |
| 139 return (_entryNode as HtmlSourceNode).scripts.contains(node); | 142 return (_entryNode as HtmlSourceNode).scripts.contains(node); |
| 140 } | 143 } |
| 141 | 144 |
| 142 void _buildDartLibrary(DartSourceNode node) { | 145 void _buildDartLibrary(DartSourceNode node) { |
| 143 var source = node.source; | 146 var source = node.source; |
| 144 // TODO(sigmund): find out from analyzer team if there is a better way | 147 // TODO(sigmund): find out from analyzer team if there is a better way |
| 145 _resolver.context.applyChanges(new ChangeSet()..changedSource(source)); | 148 _resolver.context.applyChanges(new ChangeSet()..changedSource(source)); |
| 146 var entryUnit = _resolver.context.resolveCompilationUnit2(source, source); | 149 var entryUnit = _resolver.context.resolveCompilationUnit2(source, source); |
| 147 var lib = entryUnit.element.enclosingElement; | 150 var lib = entryUnit.element.enclosingElement; |
| 148 if (!_options.checkSdk && lib.isInSdk) return; | 151 if (!_options.checkSdk && lib.isInSdk) return; |
| 149 var current = node.info; | 152 var current = node.info; |
| 150 if (current != null) { | 153 if (current != null) { |
| 151 assert(current.library == lib); | 154 assert(current.library == lib); |
| 152 } else { | 155 } else { |
| 153 node.info = current = new LibraryInfo(lib, _isEntry(node)); | 156 node.info = current = new LibraryInfo(lib, _isEntry(node)); |
| 154 } | 157 } |
| 155 _reporter.enterLibrary(current); | 158 _reporter.enterLibrary(source.uri); |
| 156 _libraries.add(current); | 159 _libraries.add(current); |
| 157 _rules.currentLibraryInfo = current; | 160 _rules.currentLibraryInfo = current; |
| 158 | 161 |
| 159 var units = [entryUnit] | 162 var units = [entryUnit] |
| 160 ..addAll(node.parts.map( | 163 ..addAll(node.parts.map( |
| 161 (p) => _resolver.context.resolveCompilationUnit2(p.source, source))); | 164 (p) => _resolver.context.resolveCompilationUnit2(p.source, source))); |
| 162 bool failureInLib = false; | 165 bool failureInLib = false; |
| 163 for (var unit in units) { | 166 for (var unit in units) { |
| 164 var unitSource = unit.element.source; | 167 var unitSource = unit.element.source; |
| 165 _reporter.enterSource(unitSource); | 168 _reporter.enterSource(unitSource); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 181 | 184 |
| 182 CheckerResults run() { | 185 CheckerResults run() { |
| 183 var clock = new Stopwatch()..start(); | 186 var clock = new Stopwatch()..start(); |
| 184 | 187 |
| 185 // TODO(sigmund): we are missing a couple failures here. The | 188 // TODO(sigmund): we are missing a couple failures here. The |
| 186 // dependendency_graph now detects broken imports or unsupported features | 189 // dependendency_graph now detects broken imports or unsupported features |
| 187 // like more than one script tag (see .severe messages in | 190 // like more than one script tag (see .severe messages in |
| 188 // dependency_graph.dart). Such failures should be reported back | 191 // dependency_graph.dart). Such failures should be reported back |
| 189 // here so we can mark failure=true in the CheckerResutls. | 192 // here so we can mark failure=true in the CheckerResutls. |
| 190 rebuild(_entryNode, _graph, _buildSource); | 193 rebuild(_entryNode, _graph, _buildSource); |
| 191 if (_options.dumpInfo && _reporter is SummaryReporter) { | 194 _dumpInfoIfRequested(); |
| 192 var result = (_reporter as SummaryReporter).result; | |
| 193 print(summaryToString(result)); | |
| 194 if (_options.dumpInfoFile != null) { | |
| 195 new File(_options.dumpInfoFile) | |
| 196 .writeAsStringSync(JSON.encode(result.toJsonMap())); | |
| 197 } | |
| 198 } | |
| 199 clock.stop(); | 195 clock.stop(); |
| 200 if (_options.serverMode) { | 196 if (_options.serverMode) { |
| 201 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); | 197 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); |
| 202 print('Compiled ${_libraries.length} libraries in ${time} s\n'); | 198 print('Compiled ${_libraries.length} libraries in ${time} s\n'); |
| 203 } | 199 } |
| 204 return new CheckerResults( | 200 return new CheckerResults( |
| 205 _libraries, _rules, _failure || _options.forceCompile); | 201 _libraries, _rules, _failure || _options.forceCompile); |
| 206 } | 202 } |
| 207 | 203 |
| 208 void _runAgain() { | 204 void _runAgain() { |
| 209 var clock = new Stopwatch()..start(); | 205 var clock = new Stopwatch()..start(); |
| 210 if (_reporter is SummaryReporter) (_reporter as SummaryReporter).clear(); | |
| 211 _libraries = <LibraryInfo>[]; | 206 _libraries = <LibraryInfo>[]; |
| 212 int changed = 0; | 207 int changed = 0; |
| 213 | 208 |
| 214 // TODO(sigmund): propagate failures here (see TODO in run). | 209 // TODO(sigmund): propagate failures here (see TODO in run). |
| 215 rebuild(_entryNode, _graph, (n) { | 210 rebuild(_entryNode, _graph, (n) { |
| 216 changed++; | 211 changed++; |
| 217 return _buildSource(n); | 212 return _buildSource(n); |
| 218 }); | 213 }); |
| 219 if (_reporter is SummaryReporter) { | |
| 220 print(summaryToString((_reporter as SummaryReporter).result)); | |
| 221 } | |
| 222 clock.stop(); | 214 clock.stop(); |
| 215 if (changed > 0) _dumpInfoIfRequested(); |
| 223 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); | 216 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); |
| 224 print("Compiled ${changed} libraries in ${time} s\n"); | 217 print("Compiled ${changed} libraries in ${time} s\n"); |
| 225 } | 218 } |
| 219 |
| 220 _dumpInfoIfRequested() { |
| 221 if (!_options.dumpInfo || _reporter is! SummaryReporter) return; |
| 222 var result = (_reporter as SummaryReporter).result; |
| 223 if (!_options.serverMode) print(summaryToString(result)); |
| 224 var filepath = _options.serverMode |
| 225 ? path.join(_options.outputDir, 'messages.json') |
| 226 : _options.dumpInfoFile; |
| 227 if (filepath == null) return; |
| 228 new File(filepath).writeAsStringSync(JSON.encode(result.toJsonMap())); |
| 229 } |
| 226 } | 230 } |
| 227 | 231 |
| 228 class CompilerServer { | 232 class CompilerServer { |
| 229 final Compiler compiler; | 233 final Compiler compiler; |
| 230 final String outDir; | 234 final String outDir; |
| 231 final int port; | 235 final int port; |
| 232 final String _entryPath; | 236 final String _entryPath; |
| 233 | 237 |
| 234 factory CompilerServer(CompilerOptions options) { | 238 factory CompilerServer(CompilerOptions options) { |
| 235 var entryPath = path.basename(options.entryPointFile); | 239 var entryPath = path.basename(options.entryPointFile); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 263 } | 267 } |
| 264 | 268 |
| 265 rebuildIfNeeded(shelf.Request request) { | 269 rebuildIfNeeded(shelf.Request request) { |
| 266 var filepath = request.url.path; | 270 var filepath = request.url.path; |
| 267 if (filepath == '/$_entryPath' || filepath == '/') compiler._runAgain(); | 271 if (filepath == '/$_entryPath' || filepath == '/') compiler._runAgain(); |
| 268 } | 272 } |
| 269 } | 273 } |
| 270 | 274 |
| 271 final _log = new Logger('dev_compiler'); | 275 final _log = new Logger('dev_compiler'); |
| 272 final _earlyErrorResult = new CheckerResults(const [], null, true); | 276 final _earlyErrorResult = new CheckerResults(const [], null, true); |
| OLD | NEW |