Chromium Code Reviews| 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. You can find the | 7 * straightforward, and essentially like an editor refactoring. You can find the |
| 8 * core implementation in [transformClass], which is ultimately called by | 8 * core implementation in [transformClass], which is ultimately called by |
| 9 * [transformObservables], the entry point to this library. | 9 * [transformObservables], the entry point to this library. |
| 10 */ | 10 */ |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 | 79 |
| 80 void transformClass(ClassDeclaration cls, TextEditTransaction code, | 80 void transformClass(ClassDeclaration cls, TextEditTransaction code, |
| 81 SourceFile file, Messages messages) { | 81 SourceFile file, Messages messages) { |
| 82 | 82 |
| 83 if (hasObservable(cls)) { | 83 if (hasObservable(cls)) { |
| 84 messages.warning('@observable on a class no longer has any effect. ' | 84 messages.warning('@observable on a class no longer has any effect. ' |
| 85 'It should be placed on individual fields.', | 85 'It should be placed on individual fields.', |
| 86 _getSpan(file, cls)); | 86 _getSpan(file, cls)); |
| 87 } | 87 } |
| 88 | 88 |
| 89 // We'd like to track whether observable was declared explicitly, otherwise | |
| 90 // report a warning later below. Because we don't have type analysis (only | |
| 91 // syntactic understanding of the code), we only report warnings that are | |
| 92 // known to be true. | |
| 93 var declaresObservable = false; | |
| 94 if (cls.extendsClause != null) { | |
| 95 var id = _getSimpleIdentifier(cls.extendsClause.superclass.name); | |
| 96 if (id.name == 'ObservableBase') { | |
| 97 code.edit(id.offset, id.end, 'ChangeNotifierBase'); | |
| 98 declaresObservable = true; | |
| 99 } else if (id.name == 'ChangeNotifierBase') { | |
| 100 declaresObservable = true; | |
| 101 } else if (id.name != 'PolymerElement' && id.name != 'Object') { | |
|
Jennifer Messerly
2013/07/31 01:51:33
include CustomElement too?
Siggi Cherem (dart-lang)
2013/07/31 02:17:29
Done
| |
| 102 // TODO(sigmund): this is conservative, consider using type-resolution to | |
| 103 // improve this check. | |
| 104 declaresObservable = true; | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 if (cls.withClause != null) { | |
| 109 for (var type in cls.withClause.mixinTypes) { | |
| 110 var id = _getSimpleIdentifier(type.name); | |
| 111 if (id.name == 'ObservableMixin') { | |
| 112 code.edit(id.offset, id.end, 'ChangeNotifierMixin'); | |
| 113 declaresObservable = true; | |
| 114 break; | |
| 115 } else if (id.name == 'ChangeNotifierMixin') { | |
| 116 declaresObservable = true; | |
| 117 break; | |
| 118 } else { | |
| 119 // TODO(sigmund): this is conservative, consider using type-resolution t o | |
|
Jennifer Messerly
2013/07/31 01:51:33
long line
Siggi Cherem (dart-lang)
2013/07/31 02:17:29
Done.
| |
| 120 // improve this check. | |
| 121 declaresObservable = true; | |
| 122 } | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 if (!declaresObservable && cls.implementsClause != null) { | |
| 127 // TODO(sigmund): consider adding type-resolution to give a more precise | |
| 128 // answer. | |
| 129 declaresObservable = true; | |
| 130 } | |
| 131 | |
| 89 // Track fields that were transformed. | 132 // Track fields that were transformed. |
| 90 var instanceFields = new Set<String>(); | 133 var instanceFields = new Set<String>(); |
| 91 var getters = new List<String>(); | 134 var getters = new List<String>(); |
| 92 var setters = new List<String>(); | 135 var setters = new List<String>(); |
| 93 | 136 |
| 94 for (var member in cls.members) { | 137 for (var member in cls.members) { |
| 95 if (member is FieldDeclaration) { | 138 if (member is FieldDeclaration) { |
| 96 bool isStatic = hasKeyword(member.keyword, Keyword.STATIC); | 139 bool isStatic = hasKeyword(member.keyword, Keyword.STATIC); |
| 97 if (isStatic) { | 140 if (isStatic) { |
| 98 if (hasObservable(member)){ | 141 if (hasObservable(member)){ |
| 99 messages.warning('Static fields can no longer be observable. ' | 142 messages.warning('Static fields can no longer be observable. ' |
| 100 'Observable fields should be put in an observable objects.', | 143 'Observable fields should be put in an observable objects.', |
| 101 _getSpan(file, member)); | 144 _getSpan(file, member)); |
| 102 } | 145 } |
| 103 continue; | 146 continue; |
| 104 } | 147 } |
| 105 if (hasObservable(member)) { | 148 if (hasObservable(member)) { |
| 149 if (!declaresObservable) { | |
| 150 messages.warning('Observable fields should be put in an observable' | |
| 151 ' objects. Please declare that this class extends from ' | |
| 152 'ObservableBase, includes ObservableMixin, or implements ' | |
| 153 'Observable.', | |
| 154 _getSpan(file, member)); | |
| 155 | |
| 156 } | |
| 106 transformFields(member.fields, code, member.offset, member.end); | 157 transformFields(member.fields, code, member.offset, member.end); |
| 107 | 158 |
| 108 var names = member.fields.variables.map((v) => v.name.name); | 159 var names = member.fields.variables.map((v) => v.name.name); |
| 109 | 160 |
| 110 getters.addAll(names); | 161 getters.addAll(names); |
| 111 if (!_isReadOnly(member.fields)) { | 162 if (!_isReadOnly(member.fields)) { |
| 112 setters.addAll(names); | 163 setters.addAll(names); |
| 113 instanceFields.addAll(names); | 164 instanceFields.addAll(names); |
| 114 } | 165 } |
| 115 } | 166 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 133 } | 184 } |
| 134 | 185 |
| 135 // Fix initializers, because they aren't allowed to call the setter. | 186 // Fix initializers, because they aren't allowed to call the setter. |
| 136 for (var member in cls.members) { | 187 for (var member in cls.members) { |
| 137 if (member is ConstructorDeclaration) { | 188 if (member is ConstructorDeclaration) { |
| 138 fixConstructor(member, code, instanceFields); | 189 fixConstructor(member, code, instanceFields); |
| 139 } | 190 } |
| 140 } | 191 } |
| 141 } | 192 } |
| 142 | 193 |
| 194 SimpleIdentifier _getSimpleIdentifier(Identifier id) => | |
| 195 id is PrefixedIdentifier ? id.identifier : id; | |
| 196 | |
| 143 | 197 |
| 144 /** | 198 /** |
| 145 * Generates `getValueWorkaround` and `setValueWorkaround`. These will go away | 199 * Generates `getValueWorkaround` and `setValueWorkaround`. These will go away |
| 146 * shortly once dart2js supports mirrors. For the moment they provide something | 200 * shortly once dart2js supports mirrors. For the moment they provide something |
| 147 * that the binding system can use. | 201 * that the binding system can use. |
| 148 */ | 202 */ |
| 149 void mirrorWorkaround(ClassDeclaration cls, TextEditTransaction code, | 203 void mirrorWorkaround(ClassDeclaration cls, TextEditTransaction code, |
| 150 List<String> getters, List<String> setters) { | 204 List<String> getters, List<String> setters) { |
| 151 | 205 |
| 152 var sb = new StringBuffer('\ngetValueWorkaround(key) {\n'); | 206 var sb = new StringBuffer('\ngetValueWorkaround(key) {\n'); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 261 $type __\$$name$initializer; | 315 $type __\$$name$initializer; |
| 262 $type get $name => __\$$name; | 316 $type get $name => __\$$name; |
| 263 set $name($type value) { | 317 set $name($type value) { |
| 264 __\$$name = notifyPropertyChange(const Symbol('$name'), __\$$name, value); | 318 __\$$name = notifyPropertyChange(const Symbol('$name'), __\$$name, value); |
| 265 } | 319 } |
| 266 '''.replaceAll('\n', '\n$indent')); | 320 '''.replaceAll('\n', '\n$indent')); |
| 267 } | 321 } |
| 268 | 322 |
| 269 code.edit(begin, end, '$replace'); | 323 code.edit(begin, end, '$replace'); |
| 270 } | 324 } |
| OLD | NEW |