Chromium Code Reviews| 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 library dev_compiler.src.codegen.dart_codegen; | 5 library dev_compiler.src.codegen.dart_codegen; |
| 6 | 6 |
| 7 import 'dart:io' show File; | 7 import 'dart:io' show File; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart' as analyzer; | 9 import 'package:analyzer/analyzer.dart' as analyzer; |
| 10 import 'package:analyzer/src/generated/ast.dart'; | 10 import 'package:analyzer/src/generated/ast.dart'; |
| 11 import 'package:analyzer/src/generated/element.dart'; | 11 import 'package:analyzer/src/generated/element.dart'; |
| 12 import 'package:analyzer/src/generated/java_core.dart' as java_core; | 12 import 'package:analyzer/src/generated/java_core.dart' as java_core; |
| 13 import 'package:analyzer/src/generated/scanner.dart' show Token; | 13 import 'package:analyzer/src/generated/scanner.dart' show Token; |
| 14 import 'package:dart_style/dart_style.dart'; | 14 import 'package:dart_style/dart_style.dart'; |
| 15 import 'package:logging/logging.dart' as logger; | 15 import 'package:logging/logging.dart' as logger; |
| 16 import 'package:path/path.dart' as path; | 16 import 'package:path/path.dart' as path; |
| 17 | 17 |
| 18 import 'package:dev_compiler/src/info.dart'; | 18 import 'package:dev_compiler/src/info.dart'; |
| 19 import 'package:dev_compiler/src/checker/rules.dart'; | 19 import 'package:dev_compiler/src/checker/rules.dart'; |
| 20 import 'package:dev_compiler/src/options.dart'; | 20 import 'package:dev_compiler/src/options.dart'; |
| 21 import 'package:dev_compiler/src/utils.dart' as utils; | 21 import 'package:dev_compiler/src/utils.dart' as utils; |
| 22 import 'ast_builder.dart'; | 22 import 'ast_builder.dart'; |
| 23 import 'code_generator.dart' as codegenerator; | 23 import 'code_generator.dart' as codegenerator; |
| 24 import 'reify_coercions.dart' as reifier; | 24 import 'reify_coercions.dart' show CoercionReifier, NewTypeIdDesc; |
| 25 | 25 |
| 26 final _log = new logger.Logger('dev_compiler.dart_codegen'); | 26 final _log = new logger.Logger('dev_compiler.dart_codegen'); |
| 27 | 27 |
| 28 class DevCompilerRuntime { | 28 class DevCompilerRuntime { |
| 29 Identifier _runtimeId = AstBuilder.identifierFromString("DEVC\$RT"); | 29 Identifier _runtimeId = AstBuilder.identifierFromString("DEVC\$RT"); |
| 30 | 30 |
| 31 Identifier _castId; | 31 Identifier _castId; |
| 32 Identifier _typeToTypeId; | 32 Identifier _typeToTypeId; |
| 33 Identifier _wrapId; | 33 Identifier _wrapId; |
| 34 | 34 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 s = d.format(s, uri: _path); | 117 s = d.format(s, uri: _path); |
| 118 } catch (e) { | 118 } catch (e) { |
| 119 _log.severe("Failed to format $_path: " + e.toString()); | 119 _log.severe("Failed to format $_path: " + e.toString()); |
| 120 } | 120 } |
| 121 } | 121 } |
| 122 _log.fine("Writing file $_path"); | 122 _log.fine("Writing file $_path"); |
| 123 new File(_path).writeAsStringSync(s); | 123 new File(_path).writeAsStringSync(s); |
| 124 } | 124 } |
| 125 } | 125 } |
| 126 | 126 |
| 127 bool _identifierNeedsQualification( | 127 bool _identifierNeedsQualification(Identifier id, NewTypeIdDesc desc) { |
| 128 Identifier id, LibraryElement current, Set<Identifier> restrict) { | 128 var library = desc.importedFrom; |
| 129 var element = id.bestElement; | 129 if (library == null) return false; |
| 130 return restrict.contains(id) && | 130 if (library.isDartCore) return false; |
| 131 element != null && | 131 if (desc.fromCurrent) return false; |
| 132 element.library != null && | 132 return true; |
| 133 (element is ClassElement || element is FunctionTypeAliasElement) && | |
| 134 !element.library.isDartCore && | |
| 135 element.library != current; | |
| 136 } | |
| 137 | |
| 138 // For every type name to which we add a reference, record the library from | |
| 139 // which it comes so that we may add it to the list of imports. | |
| 140 class UnitImportResolver extends analyzer.GeneralizingAstVisitor | |
| 141 with ConversionVisitor { | |
| 142 final CompilationUnit unit; | |
| 143 final Set<LibraryElement> imports; | |
| 144 final _currentLibrary; | |
| 145 final _newIdentifiers; | |
| 146 | |
| 147 UnitImportResolver( | |
| 148 this.unit, this._currentLibrary, this.imports, this._newIdentifiers); | |
| 149 | |
| 150 void compute() { | |
| 151 visitCompilationUnit(unit); | |
| 152 return; | |
| 153 } | |
| 154 | |
| 155 @override | |
| 156 void visitCompilationUnit(CompilationUnit node) { | |
| 157 node.declarations.forEach((node) => node.accept(this)); | |
| 158 return; | |
| 159 } | |
| 160 | |
| 161 @override | |
| 162 void visitIdentifier(Identifier id) { | |
|
Leaf
2015/04/07 22:29:58
All of this logic is now computed directly from th
| |
| 163 if (id is PrefixedIdentifier) { | |
| 164 id.prefix.accept(this); | |
| 165 return; | |
| 166 } | |
| 167 if (_identifierNeedsQualification(id, _currentLibrary, _newIdentifiers)) { | |
| 168 if (utils.isDartPrivateLibrary(id.bestElement.library)) { | |
| 169 _log.severe( | |
| 170 "Dropping import of private library ${id.bestElement.library}\n"); | |
| 171 return; | |
| 172 } | |
| 173 imports.add(id.bestElement.library); | |
| 174 } | |
| 175 return; | |
| 176 } | |
| 177 } | 133 } |
| 178 | 134 |
| 179 // This class just holds some additional syntactic helpers and | 135 // This class just holds some additional syntactic helpers and |
| 180 // fixes to the general ToSourceVisitor for use by subclasses. | 136 // fixes to the general ToSourceVisitor for use by subclasses. |
| 181 abstract class UnitGeneratorCommon extends analyzer.ToSourceVisitor { | 137 abstract class UnitGeneratorCommon extends analyzer.ToSourceVisitor { |
| 182 UnitGeneratorCommon(java_core.PrintWriter out) : super(out); | 138 UnitGeneratorCommon(java_core.PrintWriter out) : super(out); |
| 183 | 139 |
| 184 void output(String s); | 140 void output(String s); |
| 185 void outputln(String s); | 141 void outputln(String s); |
| 186 | 142 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 } | 225 } |
| 270 | 226 |
| 271 // TODO(leafp) Not sure if this is the right way to generate | 227 // TODO(leafp) Not sure if this is the right way to generate |
| 272 // Dart source going forward, but it's a quick way to get started. | 228 // Dart source going forward, but it's a quick way to get started. |
| 273 class UnitGenerator extends UnitGeneratorCommon with ConversionVisitor<Object> { | 229 class UnitGenerator extends UnitGeneratorCommon with ConversionVisitor<Object> { |
| 274 CompilationUnit unit; | 230 CompilationUnit unit; |
| 275 final java_core.PrintWriter _out; | 231 final java_core.PrintWriter _out; |
| 276 final String outDir; | 232 final String outDir; |
| 277 Set<LibraryElement> _extraImports; | 233 Set<LibraryElement> _extraImports; |
| 278 final _runtime = new DevCompilerRuntime(); | 234 final _runtime = new DevCompilerRuntime(); |
| 279 LibraryElement _currentLibrary; | |
| 280 bool _qualifyNames = true; | 235 bool _qualifyNames = true; |
| 281 Set<Identifier> _newIdentifiers; | 236 Map<Identifier, NewTypeIdDesc> _newIdentifiers; |
| 282 | 237 |
| 283 UnitGenerator(this.unit, java_core.PrintWriter out, String this.outDir, | 238 UnitGenerator(this.unit, java_core.PrintWriter out, String this.outDir, |
| 284 this._extraImports, this._newIdentifiers) | 239 this._extraImports, this._newIdentifiers) |
| 285 : _out = out, | 240 : _out = out, |
| 286 super(out) { | 241 super(out); |
| 287 _currentLibrary = unit.element.enclosingElement; | |
| 288 final UnitImportResolver r = new UnitImportResolver( | |
| 289 unit, _currentLibrary, _extraImports, _newIdentifiers); | |
| 290 r.compute(); | |
| 291 } | |
| 292 | 242 |
| 293 void output(String s) => _out.print(s); | 243 void output(String s) => _out.print(s); |
| 294 void outputln(String s) => _out.println(s); | 244 void outputln(String s) => _out.println(s); |
| 295 | 245 |
| 296 // Choose a canonical prefix for a library that we are adding. | 246 // Choose a canonical prefix for a library that we are adding. |
| 297 // Currently just chooses something unlikely to conflict with a user | 247 // Currently just chooses something unlikely to conflict with a user |
| 298 // prefix. | 248 // prefix. |
| 299 // TODO(leafp): Make this robust. | 249 // TODO(leafp): Make this robust. |
| 300 String canonizeLibraryName(String name) { | 250 String canonizeLibraryName(String name) { |
| 301 name = name.replaceAll(".", "DOT"); | 251 name = name.replaceAll(".", "DOT"); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 @override | 333 @override |
| 384 Object visitPrefixedIdentifier(PrefixedIdentifier id) { | 334 Object visitPrefixedIdentifier(PrefixedIdentifier id) { |
| 385 safelyVisitNode(id.prefix); | 335 safelyVisitNode(id.prefix); |
| 386 output('.'); | 336 output('.'); |
| 387 output(id.identifier.token.lexeme); | 337 output(id.identifier.token.lexeme); |
| 388 return null; | 338 return null; |
| 389 } | 339 } |
| 390 | 340 |
| 391 @override | 341 @override |
| 392 Object visitSimpleIdentifier(SimpleIdentifier id) { | 342 Object visitSimpleIdentifier(SimpleIdentifier id) { |
| 393 var element = id.bestElement; | 343 if (!(_qualifyNames |
| 394 if (!(_qualifyNames && | 344 && _newIdentifiers.containsKey(id) |
| 395 _identifierNeedsQualification(id, _currentLibrary, _newIdentifiers))) { | 345 && _identifierNeedsQualification(id, _newIdentifiers[id]))) { |
| 396 return super.visitSimpleIdentifier(id); | 346 return super.visitSimpleIdentifier(id); |
| 397 } | 347 } |
| 398 if (!utils.isDartPrivateLibrary(element.library)) { | 348 var library = _newIdentifiers[id].importedFrom; |
| 399 var lib = utils.canonicalLibraryName(element.library); | 349 if (!utils.isDartPrivateLibrary(library)) { |
| 350 var lib = utils.canonicalLibraryName(library); | |
| 400 var libname = canonizeLibraryName(lib); | 351 var libname = canonizeLibraryName(lib); |
| 401 output(libname); | 352 output(libname); |
| 402 output('.'); | 353 output('.'); |
| 403 } | 354 } |
| 404 output(id.name); | 355 output(id.name); |
| 405 return null; | 356 return null; |
| 406 } | 357 } |
| 407 | 358 |
| 408 void generate() { | 359 void generate() { |
| 409 visitCompilationUnit(unit); | 360 visitCompilationUnit(unit); |
| 410 } | 361 } |
| 411 } | 362 } |
| 412 | 363 |
| 413 class DartGenerator extends codegenerator.CodeGenerator { | 364 class DartGenerator extends codegenerator.CodeGenerator { |
| 414 final CompilerOptions options; | 365 final CompilerOptions options; |
| 415 reifier.VariableManager _vm; | |
| 416 Set<LibraryElement> _extraImports; | |
| 417 TypeRules _rules; | 366 TypeRules _rules; |
| 418 | 367 |
| 419 DartGenerator(String outDir, Uri root, TypeRules rules, this.options) | 368 DartGenerator(String outDir, Uri root, TypeRules rules, this.options) |
| 420 : _rules = rules, | 369 : _rules = rules, |
| 421 super(outDir, root, rules); | 370 super(outDir, root, rules); |
| 422 | 371 |
| 423 void generateUnit(CompilationUnit unit, LibraryInfo info, String libraryDir) { | 372 Set<LibraryElement> computeExtraImports(Map<Identifier, NewTypeIdDesc> ids) { |
|
Leaf
2015/04/07 22:29:58
This seemed kind of pointless as a separate functi
Jennifer Messerly
2015/04/08 20:28:16
+1, looks nice
| |
| 424 var uri = unit.element.source.uri; | 373 var imports = new Set<LibraryElement>(); |
| 425 _log.fine("Generating unit " + uri.toString()); | 374 void process(Identifier id, NewTypeIdDesc desc) { |
| 426 FileWriter out = new FileWriter( | 375 if (_identifierNeedsQualification(id, desc)) { |
| 427 options, path.join(libraryDir, '${uri.pathSegments.last}')); | 376 var library = desc.importedFrom; |
| 428 var tm = new reifier.TypeManager(_vm); | 377 if (utils.isDartPrivateLibrary(library)) { |
| 429 var r = new reifier.UnitCoercionReifier(tm, _vm, _rules); | 378 _log.severe( |
| 430 r.reify(unit); | 379 "Dropping import of private library ${library}\n"); |
| 431 var ids = new Set<Identifier>.from(tm.addedTypes.map((tn) => tn.name)); | 380 return; |
| 432 var unitGen = new UnitGenerator(unit, out, outDir, _extraImports, ids); | 381 } |
| 433 unitGen.generate(); | 382 imports.add(library); |
| 434 out.finalize(); | 383 } |
| 384 } | |
| 385 ids.forEach(process); | |
| 386 return imports; | |
| 435 } | 387 } |
| 436 | 388 |
| 437 String generateLibrary(LibraryUnit library, LibraryInfo info) { | 389 String generateLibrary(LibraryUnit library, LibraryInfo info) { |
| 438 _vm = new reifier.VariableManager(); | 390 var r = new CoercionReifier(library, rules); |
| 439 _extraImports = new Set<LibraryElement>(); | 391 var ids = r.reify(); |
| 392 var extraImports = computeExtraImports(ids); | |
| 440 | 393 |
| 441 for (var unit in library.partsThenLibrary) { | 394 for (var unit in library.partsThenLibrary) { |
| 442 var outputDir = makeOutputDirectory(info, unit); | 395 var libraryDir = makeOutputDirectory(info, unit); |
| 443 generateUnit(unit, info, outputDir); | 396 var uri = unit.element.source.uri; |
| 397 _log.fine("Generating unit " + uri.toString()); | |
|
Jennifer Messerly
2015/04/08 20:28:16
"Generating unit $uri" ?
| |
| 398 FileWriter out = new FileWriter( | |
| 399 options, path.join(libraryDir, '${uri.pathSegments.last}')); | |
| 400 var unitGen = new UnitGenerator(unit, out, outDir, extraImports, ids); | |
| 401 unitGen.generate(); | |
| 402 out.finalize(); | |
| 444 } | 403 } |
| 445 | 404 |
| 446 _extraImports = null; | |
| 447 _vm = null; | |
| 448 return null; | 405 return null; |
| 449 } | 406 } |
| 450 } | 407 } |
| 451 | 408 |
| 452 class EmptyUnitGenerator extends UnitGeneratorCommon { | 409 class EmptyUnitGenerator extends UnitGeneratorCommon { |
| 453 final java_core.PrintWriter _out; | 410 final java_core.PrintWriter _out; |
| 454 CompilationUnit unit; | 411 CompilationUnit unit; |
| 455 | 412 |
| 456 EmptyUnitGenerator(this.unit, java_core.PrintWriter out) | 413 EmptyUnitGenerator(this.unit, java_core.PrintWriter out) |
| 457 : _out = out, | 414 : _out = out, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 483 void generateUnit(CompilationUnit unit, LibraryInfo info, String libraryDir) { | 440 void generateUnit(CompilationUnit unit, LibraryInfo info, String libraryDir) { |
| 484 var uri = unit.element.source.uri; | 441 var uri = unit.element.source.uri; |
| 485 _log.fine("Emitting original unit " + uri.toString()); | 442 _log.fine("Emitting original unit " + uri.toString()); |
| 486 FileWriter out = new FileWriter( | 443 FileWriter out = new FileWriter( |
| 487 options, path.join(libraryDir, '${uri.pathSegments.last}')); | 444 options, path.join(libraryDir, '${uri.pathSegments.last}')); |
| 488 var unitGen = new EmptyUnitGenerator(unit, out); | 445 var unitGen = new EmptyUnitGenerator(unit, out); |
| 489 unitGen.generate(); | 446 unitGen.generate(); |
| 490 out.finalize(); | 447 out.finalize(); |
| 491 } | 448 } |
| 492 } | 449 } |
| OLD | NEW |