Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: pkg/observe/lib/transform.dart

Issue 26967004: add @MirrorsUsed to observe/polymer/polymer_exprs pkgs (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fix typo in comment Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 } 97 }
98 98
99 class _ErrorCollector extends AnalysisErrorListener { 99 class _ErrorCollector extends AnalysisErrorListener {
100 final errors = <AnalysisError>[]; 100 final errors = <AnalysisError>[];
101 onError(error) => errors.add(error); 101 onError(error) => errors.add(error);
102 } 102 }
103 103
104 _getSpan(SourceFile file, ASTNode node) => file.span(node.offset, node.end); 104 _getSpan(SourceFile file, ASTNode node) => file.span(node.offset, node.end);
105 105
106 /** True if the node has the `@observable` or `@published` annotation. */ 106 /** True if the node has the `@observable` or `@published` annotation. */
107 // TODO(jmesserly): it is not good to be hard coding these. We should do a 107 // TODO(jmesserly): it is not good to be hard coding Polymer support here.
108 // resolve and do a proper ObservableProperty subtype check. However resolve
109 // is very expensive in analyzer_experimental, so it isn't feasible yet.
110 bool _hasObservable(AnnotatedNode node) => 108 bool _hasObservable(AnnotatedNode node) =>
111 _hasAnnotation(node, 'observable') || _hasAnnotation(node, 'published'); 109 node.metadata.any(_isObservableAnnotation);
112 110
113 bool _hasAnnotation(AnnotatedNode node, String name) { 111 // TODO(jmesserly): this isn't correct if the annotation has been imported
114 // TODO(jmesserly): this isn't correct if the annotation has been imported 112 // with a prefix, or cases like that. We should technically be resolving, but
115 // with a prefix, or cases like that. We should technically be resolving, but 113 // that is expensive in analyzer_experimental, so it isn't feasible yet.
116 // that is expensive. 114 bool _isObservableAnnotation(Annotation node) =>
117 return node.metadata.any((m) => m.name.name == name && 115 _isAnnotationContant(node, 'observable') ||
118 m.constructorName == null && m.arguments == null); 116 _isAnnotationContant(node, 'published') ||
119 } 117 _isAnnotationType(node, 'ObservableProperty') ||
118 _isAnnotationType(node, 'PublishedProperty');
119
120 bool _isAnnotationContant(Annotation m, String name) =>
121 m.name.name == name && m.constructorName == null && m.arguments == null;
122
123 bool _isAnnotationType(Annotation m, String name) => m.name == name;
120 124
121 void _transformClass(ClassDeclaration cls, TextEditTransaction code, 125 void _transformClass(ClassDeclaration cls, TextEditTransaction code,
122 SourceFile file, TransformLogger logger) { 126 SourceFile file, TransformLogger logger) {
123 127
124 if (_hasObservable(cls)) { 128 if (_hasObservable(cls)) {
125 logger.warning('@observable on a class no longer has any effect. ' 129 logger.warning('@observable on a class no longer has any effect. '
126 'It should be placed on individual fields.', 130 'It should be placed on individual fields.',
127 span: _getSpan(file, cls)); 131 span: _getSpan(file, cls));
128 } 132 }
129 133
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 // @otherMetaData 334 // @otherMetaData
331 // Foo 335 // Foo
332 // foo = 1, bar = 2, 336 // foo = 1, bar = 2,
333 // baz; 337 // baz;
334 // 338 //
335 // Will be transformed into something like: 339 // Will be transformed into something like:
336 // 340 //
337 // @observable 341 // @observable
338 // @OtherMetaData() 342 // @OtherMetaData()
339 // Foo 343 // Foo
340 // get foo => __foo; Foo __foo = 1; set foo ...; ... bar ... 344 // get foo => __foo; Foo __foo = 1; @reflectable set foo ...; ...
341 // @observable @OtherMetaData() Foo get baz => __baz; Foo baz; ... 345 // @observable @OtherMetaData() Foo get baz => __baz; Foo baz; ...
Siggi Cherem (dart-lang) 2013/10/15 21:52:18 should we include @reflectable on the 'get' part o
Jennifer Messerly 2013/10/15 22:03:29 good catch.
342 // 346 //
343 // Metadata is moved to the getter. 347 // Metadata is moved to the getter.
344 348
345 String metadata = ''; 349 String metadata = '';
346 if (fields.variables.length > 1) { 350 if (fields.variables.length > 1) {
347 metadata = member.metadata 351 metadata = member.metadata
348 .map((m) => _getOriginalCode(code, m)) 352 .map((m) => _getOriginalCode(code, m))
349 .join(' '); 353 .join(' ');
354 metadata = '@reflectable $metadata';
350 } 355 }
351 356
352 for (int i = 0; i < fields.variables.length; i++) { 357 for (int i = 0; i < fields.variables.length; i++) {
353 final field = fields.variables[i]; 358 final field = fields.variables[i];
354 final name = field.name.name; 359 final name = field.name.name;
355 360
356 var beforeInit = 'get $name => __\$$name; $type __\$$name'; 361 var beforeInit = 'get $name => __\$$name; $type __\$$name';
357 362
358 // The first field is expanded differently from subsequent fields, because 363 // The first field is expanded differently from subsequent fields, because
359 // we can reuse the metadata and type annotation. 364 // we can reuse the metadata and type annotation.
360 if (i > 0) beforeInit = '$metadata $type $beforeInit'; 365 if (i == 0) {
366 final begin = member.metadata.first.offset;
367 code.edit(begin, begin, '@reflectable ');
368 } else {
369 beforeInit = '$metadata $type $beforeInit';
370 }
361 371
362 code.edit(field.name.offset, field.name.end, beforeInit); 372 code.edit(field.name.offset, field.name.end, beforeInit);
363 373
364 // Replace comma with semicolon 374 // Replace comma with semicolon
365 final end = _findFieldSeperator(field.endToken.next); 375 final end = _findFieldSeperator(field.endToken.next);
366 if (end.type == TokenType.COMMA) code.edit(end.offset, end.end, ';'); 376 if (end.type == TokenType.COMMA) code.edit(end.offset, end.end, ';');
367 377
368 code.edit(end.end, end.end, ' set $name($type value) { ' 378 code.edit(end.end, end.end, ' @reflectable set $name($type value) { '
369 '__\$$name = notifyPropertyChange(#$name, __\$$name, value); }'); 379 '__\$$name = notifyPropertyChange(#$name, __\$$name, value); }');
370 } 380 }
371 } 381 }
372 382
373 Token _findFieldSeperator(Token token) { 383 Token _findFieldSeperator(Token token) {
374 while (token != null) { 384 while (token != null) {
375 if (token.type == TokenType.COMMA || token.type == TokenType.SEMICOLON) { 385 if (token.type == TokenType.COMMA || token.type == TokenType.SEMICOLON) {
376 break; 386 break;
377 } 387 }
378 token = token.next; 388 token = token.next;
379 } 389 }
380 return token; 390 return token;
381 } 391 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698