| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /** | 5 /** |
| 6 * Code transform for @observable. The core transformation is relatively | 6 * Code transform for @observable. The core transformation is relatively |
| 7 * straightforward, and essentially like an editor refactoring. | 7 * straightforward, and essentially like an editor refactoring. |
| 8 */ | 8 */ |
| 9 library observe.transform; | 9 library observe.transform; |
| 10 | 10 |
| 11 import 'dart:async'; | 11 import 'dart:async'; |
| 12 import 'package:path/path.dart' as path; | 12 import 'package:path/path.dart' as path; |
| 13 import 'package:analyzer_experimental/src/generated/ast.dart'; | 13 import 'package:analyzer_experimental/src/generated/ast.dart'; |
| 14 import 'package:analyzer_experimental/src/generated/error.dart'; | 14 import 'package:analyzer_experimental/src/generated/error.dart'; |
| 15 import 'package:analyzer_experimental/src/generated/parser.dart'; | 15 import 'package:analyzer_experimental/src/generated/parser.dart'; |
| 16 import 'package:analyzer_experimental/src/generated/scanner.dart'; | 16 import 'package:analyzer_experimental/src/generated/scanner.dart'; |
| 17 import 'package:barback/barback.dart'; | 17 import 'package:barback/barback.dart'; |
| 18 import 'package:source_maps/refactor.dart'; | 18 import 'package:source_maps/refactor.dart'; |
| 19 import 'package:source_maps/span.dart' show SourceFile; | 19 import 'package:source_maps/span.dart' show SourceFile; |
| 20 | 20 |
| 21 /** | 21 /** |
| 22 * A [Transformer] that replaces observables based on dirty-checking with an | 22 * A [Transformer] that replaces observables based on dirty-checking with an |
| 23 * implementation based on change notifications. | 23 * implementation based on change notifications. |
| 24 * | 24 * |
| 25 * The transformation adds hooks for field setters and notifies the observation | 25 * The transformation adds hooks for field setters and notifies the observation |
| 26 * system of the change. | 26 * system of the change. |
| 27 */ | 27 */ |
| 28 class ObservableTransformer extends Transformer { | 28 class ObservableTransformer extends Transformer { |
| 29 | 29 |
| 30 Future<bool> isPrimary(Asset input) { | 30 Future<bool> isPrimary(Asset input) { |
| 31 if (input.id.extension != '.dart') return new Future.value(false); | 31 if (input.id.extension != '.dart') return new Future.value(false); |
| 32 // Note: technically we should parse the file to find accurately the | 32 // Note: technically we should parse the file to find accurately the |
| 33 // observable annotation, but that seems expensive. It would require almost | 33 // observable annotation, but that seems expensive. It would require almost |
| 34 // as much work as applying the transform. We rather have some false | 34 // as much work as applying the transform. We rather have some false |
| 35 // positives here, and then generate no outputs when we apply this | 35 // positives here, and then generate no outputs when we apply this |
| 36 // transform. | 36 // transform. |
| 37 return input.readAsString().then((c) => c.contains("@observable")); | 37 return input.readAsString().then((c) => c.contains("@observable")); |
| 38 } | 38 } |
| 39 | 39 |
| 40 Future apply(Transform transform) { | 40 Future apply(Transform transform) { |
| 41 return transform.primaryInput | 41 return transform.primaryInput.readAsString().then((content) { |
| 42 .then((input) => input.readAsString().then((content) { | 42 var id = transform.primaryInput.id; |
| 43 var id = transform.primaryId; | |
| 44 // TODO(sigmund): improve how we compute this url | 43 // TODO(sigmund): improve how we compute this url |
| 45 var url = id.path.startsWith('lib/') | 44 var url = id.path.startsWith('lib/') |
| 46 ? 'package:${id.package}/${id.path.substring(4)}' : id.path; | 45 ? 'package:${id.package}/${id.path.substring(4)}' : id.path; |
| 47 var sourceFile = new SourceFile.text(url, content); | 46 var sourceFile = new SourceFile.text(url, content); |
| 48 var transaction = _transformCompilationUnit( | 47 var transaction = _transformCompilationUnit( |
| 49 content, sourceFile, transform.logger); | 48 content, sourceFile, transform.logger); |
| 50 if (!transaction.hasEdits) { | 49 if (!transaction.hasEdits) { |
| 51 transform.addOutput(input); | 50 transform.addOutput(input); |
| 52 return; | 51 return; |
| 53 } | 52 } |
| 54 var printer = transaction.commit(); | 53 var printer = transaction.commit(); |
| 55 // TODO(sigmund): emit source maps when barback supports it (see | 54 // TODO(sigmund): emit source maps when barback supports it (see |
| 56 // dartbug.com/12340) | 55 // dartbug.com/12340) |
| 57 printer.build(url); | 56 printer.build(url); |
| 58 transform.addOutput(new Asset.fromString(id, printer.text)); | 57 transform.addOutput(new Asset.fromString(id, printer.text)); |
| 59 })); | 58 }); |
| 60 } | 59 } |
| 61 } | 60 } |
| 62 | 61 |
| 63 TextEditTransaction _transformCompilationUnit( | 62 TextEditTransaction _transformCompilationUnit( |
| 64 String inputCode, SourceFile sourceFile, TransformLogger logger) { | 63 String inputCode, SourceFile sourceFile, TransformLogger logger) { |
| 65 var unit = _parseCompilationUnit(inputCode); | 64 var unit = _parseCompilationUnit(inputCode); |
| 66 return transformObservables(unit, sourceFile, inputCode, logger); | 65 return transformObservables(unit, sourceFile, inputCode, logger); |
| 67 } | 66 } |
| 68 | 67 |
| 69 // TODO(sigmund): make this private. This is currently public so it can be used | 68 // TODO(sigmund): make this private. This is currently public so it can be used |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 $type __\$$name$initializer; | 328 $type __\$$name$initializer; |
| 330 $type get $name => __\$$name; | 329 $type get $name => __\$$name; |
| 331 set $name($type value) { | 330 set $name($type value) { |
| 332 __\$$name = notifyPropertyChange(const Symbol('$name'), __\$$name, value); | 331 __\$$name = notifyPropertyChange(const Symbol('$name'), __\$$name, value); |
| 333 } | 332 } |
| 334 '''.replaceAll('\n', '\n$indent')); | 333 '''.replaceAll('\n', '\n$indent')); |
| 335 } | 334 } |
| 336 | 335 |
| 337 code.edit(begin, end, '$replace'); | 336 code.edit(begin, end, '$replace'); |
| 338 } | 337 } |
| OLD | NEW |