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 | 12 |
13 import 'package:analyzer_experimental/src/generated/java_core.dart' show CharSeq
uence; | 13 import 'package:analyzer/src/generated/java_core.dart' show CharSequence; |
14 import 'package:analyzer_experimental/src/generated/ast.dart'; | 14 import 'package:analyzer/src/generated/ast.dart'; |
15 import 'package:analyzer_experimental/src/generated/error.dart'; | 15 import 'package:analyzer/src/generated/error.dart'; |
16 import 'package:analyzer_experimental/src/generated/parser.dart'; | 16 import 'package:analyzer/src/generated/parser.dart'; |
17 import 'package:analyzer_experimental/src/generated/scanner.dart'; | 17 import 'package:analyzer/src/generated/scanner.dart'; |
18 import 'package:barback/barback.dart'; | 18 import 'package:barback/barback.dart'; |
19 import 'package:source_maps/refactor.dart'; | 19 import 'package:source_maps/refactor.dart'; |
20 import 'package:source_maps/span.dart' show SourceFile; | 20 import 'package:source_maps/span.dart' show SourceFile; |
21 | 21 |
22 /** | 22 /** |
23 * A [Transformer] that replaces observables based on dirty-checking with an | 23 * A [Transformer] that replaces observables based on dirty-checking with an |
24 * implementation based on change notifications. | 24 * implementation based on change notifications. |
25 * | 25 * |
26 * The transformation adds hooks for field setters and notifies the observation | 26 * The transformation adds hooks for field setters and notifies the observation |
27 * system of the change. | 27 * system of the change. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 if (_hasObservable(declaration)) { | 81 if (_hasObservable(declaration)) { |
82 logger.warning('Top-level fields can no longer be observable. ' | 82 logger.warning('Top-level fields can no longer be observable. ' |
83 'Observable fields should be put in an observable objects.', | 83 'Observable fields should be put in an observable objects.', |
84 span: _getSpan(sourceFile, declaration)); | 84 span: _getSpan(sourceFile, declaration)); |
85 } | 85 } |
86 } | 86 } |
87 } | 87 } |
88 return code; | 88 return code; |
89 } | 89 } |
90 | 90 |
91 /** Parse [code] using analyzer_experimental. */ | 91 /** Parse [code] using analyzer. */ |
92 CompilationUnit _parseCompilationUnit(String code) { | 92 CompilationUnit _parseCompilationUnit(String code) { |
93 var errorListener = new _ErrorCollector(); | 93 var errorListener = new _ErrorCollector(); |
94 var reader = new CharSequenceReader(new CharSequence(code)); | 94 var reader = new CharSequenceReader(new CharSequence(code)); |
95 var scanner = new Scanner(null, reader, errorListener); | 95 var scanner = new Scanner(null, reader, errorListener); |
96 var token = scanner.tokenize(); | 96 var token = scanner.tokenize(); |
97 var parser = new Parser(null, errorListener); | 97 var parser = new Parser(null, errorListener); |
98 return parser.parseCompilationUnit(token); | 98 return parser.parseCompilationUnit(token); |
99 } | 99 } |
100 | 100 |
101 class _ErrorCollector extends AnalysisErrorListener { | 101 class _ErrorCollector extends AnalysisErrorListener { |
102 final errors = <AnalysisError>[]; | 102 final errors = <AnalysisError>[]; |
103 onError(error) => errors.add(error); | 103 onError(error) => errors.add(error); |
104 } | 104 } |
105 | 105 |
106 _getSpan(SourceFile file, ASTNode node) => file.span(node.offset, node.end); | 106 _getSpan(SourceFile file, ASTNode node) => file.span(node.offset, node.end); |
107 | 107 |
108 /** True if the node has the `@observable` or `@published` annotation. */ | 108 /** True if the node has the `@observable` or `@published` annotation. */ |
109 // TODO(jmesserly): it is not good to be hard coding Polymer support here. | 109 // TODO(jmesserly): it is not good to be hard coding Polymer support here. |
110 bool _hasObservable(AnnotatedNode node) => | 110 bool _hasObservable(AnnotatedNode node) => |
111 node.metadata.any(_isObservableAnnotation); | 111 node.metadata.any(_isObservableAnnotation); |
112 | 112 |
113 // TODO(jmesserly): this isn't correct if the annotation has been imported | 113 // TODO(jmesserly): this isn't correct if the annotation has been imported |
114 // with a prefix, or cases like that. We should technically be resolving, but | 114 // with a prefix, or cases like that. We should technically be resolving, but |
115 // that is expensive in analyzer_experimental, so it isn't feasible yet. | 115 // that is expensive in analyzer, so it isn't feasible yet. |
116 bool _isObservableAnnotation(Annotation node) => | 116 bool _isObservableAnnotation(Annotation node) => |
117 _isAnnotationContant(node, 'observable') || | 117 _isAnnotationContant(node, 'observable') || |
118 _isAnnotationContant(node, 'published') || | 118 _isAnnotationContant(node, 'published') || |
119 _isAnnotationType(node, 'ObservableProperty') || | 119 _isAnnotationType(node, 'ObservableProperty') || |
120 _isAnnotationType(node, 'PublishedProperty'); | 120 _isAnnotationType(node, 'PublishedProperty'); |
121 | 121 |
122 bool _isAnnotationContant(Annotation m, String name) => | 122 bool _isAnnotationContant(Annotation m, String name) => |
123 m.name.name == name && m.constructorName == null && m.arguments == null; | 123 m.name.name == name && m.constructorName == null && m.arguments == null; |
124 | 124 |
125 bool _isAnnotationType(Annotation m, String name) => m.name == name; | 125 bool _isAnnotationType(Annotation m, String name) => m.name == name; |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 | 406 |
407 Token _findFieldSeperator(Token token) { | 407 Token _findFieldSeperator(Token token) { |
408 while (token != null) { | 408 while (token != null) { |
409 if (token.type == TokenType.COMMA || token.type == TokenType.SEMICOLON) { | 409 if (token.type == TokenType.COMMA || token.type == TokenType.SEMICOLON) { |
410 break; | 410 break; |
411 } | 411 } |
412 token = token.next; | 412 token = token.next; |
413 } | 413 } |
414 return token; | 414 return token; |
415 } | 415 } |
OLD | NEW |