| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 analyzer.src.dart.element.element; | 5 library analyzer.src.dart.element.element; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:math' show min; | 8 import 'dart:math' show min; |
| 9 | 9 |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 /** | 502 /** |
| 503 * Set whether this class is abstract. | 503 * Set whether this class is abstract. |
| 504 */ | 504 */ |
| 505 void set abstract(bool isAbstract) { | 505 void set abstract(bool isAbstract) { |
| 506 _assertNotResynthesized(_unlinkedClass); | 506 _assertNotResynthesized(_unlinkedClass); |
| 507 setModifier(Modifier.ABSTRACT, isAbstract); | 507 setModifier(Modifier.ABSTRACT, isAbstract); |
| 508 } | 508 } |
| 509 | 509 |
| 510 @override | 510 @override |
| 511 List<PropertyAccessorElement> get accessors { | 511 List<PropertyAccessorElement> get accessors { |
| 512 if (_unlinkedClass != null && _accessors == null) { | 512 if (_accessors == null) { |
| 513 _resynthesizeFieldsAndPropertyAccessors(); | 513 if (_kernel != null || _unlinkedClass != null) { |
| 514 _resynthesizeFieldsAndPropertyAccessors(); |
| 515 } |
| 514 } | 516 } |
| 515 return _accessors ?? const <PropertyAccessorElement>[]; | 517 return _accessors ?? const <PropertyAccessorElement>[]; |
| 516 } | 518 } |
| 517 | 519 |
| 518 @override | 520 @override |
| 519 void set accessors(List<PropertyAccessorElement> accessors) { | 521 void set accessors(List<PropertyAccessorElement> accessors) { |
| 520 _assertNotResynthesized(_unlinkedClass); | 522 _assertNotResynthesized(_unlinkedClass); |
| 521 super.accessors = accessors; | 523 super.accessors = accessors; |
| 522 } | 524 } |
| 523 | 525 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 } | 645 } |
| 644 } | 646 } |
| 645 return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible); | 647 return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible); |
| 646 } | 648 } |
| 647 | 649 |
| 648 @override | 650 @override |
| 649 TypeParameterizedElementMixin get enclosingTypeParameterContext => null; | 651 TypeParameterizedElementMixin get enclosingTypeParameterContext => null; |
| 650 | 652 |
| 651 @override | 653 @override |
| 652 List<FieldElement> get fields { | 654 List<FieldElement> get fields { |
| 653 if (_unlinkedClass != null && _fields == null) { | 655 if (_fields == null) { |
| 654 _resynthesizeFieldsAndPropertyAccessors(); | 656 if (_kernel != null || _unlinkedClass != null) { |
| 657 _resynthesizeFieldsAndPropertyAccessors(); |
| 658 } |
| 655 } | 659 } |
| 656 return _fields ?? const <FieldElement>[]; | 660 return _fields ?? const <FieldElement>[]; |
| 657 } | 661 } |
| 658 | 662 |
| 659 @override | 663 @override |
| 660 void set fields(List<FieldElement> fields) { | 664 void set fields(List<FieldElement> fields) { |
| 661 _assertNotResynthesized(_unlinkedClass); | 665 _assertNotResynthesized(_unlinkedClass); |
| 662 super.fields = fields; | 666 super.fields = fields; |
| 663 } | 667 } |
| 664 | 668 |
| (...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1223 }).toList(growable: false); | 1227 }).toList(growable: false); |
| 1224 } | 1228 } |
| 1225 | 1229 |
| 1226 /** | 1230 /** |
| 1227 * Resynthesize explicit fields and property accessors and fill [_fields] and | 1231 * Resynthesize explicit fields and property accessors and fill [_fields] and |
| 1228 * [_accessors] with explicit and implicit elements. | 1232 * [_accessors] with explicit and implicit elements. |
| 1229 */ | 1233 */ |
| 1230 void _resynthesizeFieldsAndPropertyAccessors() { | 1234 void _resynthesizeFieldsAndPropertyAccessors() { |
| 1231 assert(_fields == null); | 1235 assert(_fields == null); |
| 1232 assert(_accessors == null); | 1236 assert(_accessors == null); |
| 1233 // Build explicit fields and implicit property accessors. | |
| 1234 var explicitFields = <FieldElement>[]; | 1237 var explicitFields = <FieldElement>[]; |
| 1235 var implicitAccessors = <PropertyAccessorElement>[]; | 1238 var implicitAccessors = <PropertyAccessorElement>[]; |
| 1236 for (UnlinkedVariable v in _unlinkedClass.fields) { | |
| 1237 FieldElementImpl field = | |
| 1238 new FieldElementImpl.forSerializedFactory(v, this); | |
| 1239 explicitFields.add(field); | |
| 1240 implicitAccessors.add( | |
| 1241 new PropertyAccessorElementImpl_ImplicitGetter(field) | |
| 1242 ..enclosingElement = this); | |
| 1243 if (!field.isConst && !field.isFinal) { | |
| 1244 implicitAccessors.add( | |
| 1245 new PropertyAccessorElementImpl_ImplicitSetter(field) | |
| 1246 ..enclosingElement = this); | |
| 1247 } | |
| 1248 } | |
| 1249 // Build explicit property accessors and implicit fields. | |
| 1250 var explicitAccessors = <PropertyAccessorElement>[]; | 1239 var explicitAccessors = <PropertyAccessorElement>[]; |
| 1251 var implicitFields = <String, FieldElementImpl>{}; | 1240 var implicitFields = <String, FieldElementImpl>{}; |
| 1252 for (UnlinkedExecutable e in _unlinkedClass.executables) { | 1241 if (_kernel != null) { |
| 1253 if (e.kind == UnlinkedExecutableKind.getter || | 1242 // Build explicit fields and implicit property accessors. |
| 1254 e.kind == UnlinkedExecutableKind.setter) { | 1243 for (var k in _kernel.fields) { |
| 1255 PropertyAccessorElementImpl accessor = | 1244 var field = new FieldElementImpl.forKernelFactory(this, k); |
| 1256 new PropertyAccessorElementImpl.forSerialized(e, this); | 1245 explicitFields.add(field); |
| 1257 explicitAccessors.add(accessor); | 1246 implicitAccessors.add( |
| 1258 // Create or update the implicit field. | 1247 new PropertyAccessorElementImpl_ImplicitGetter(field) |
| 1259 String fieldName = accessor.displayName; | 1248 ..enclosingElement = this); |
| 1260 FieldElementImpl field = implicitFields[fieldName]; | 1249 if (!field.isConst && !field.isFinal) { |
| 1261 if (field == null) { | 1250 implicitAccessors.add( |
| 1262 field = new FieldElementImpl(fieldName, -1); | 1251 new PropertyAccessorElementImpl_ImplicitSetter(field) |
| 1263 implicitFields[fieldName] = field; | 1252 ..enclosingElement = this); |
| 1264 field.enclosingElement = this; | |
| 1265 field.isSynthetic = true; | |
| 1266 field.isFinal = e.kind == UnlinkedExecutableKind.getter; | |
| 1267 field.isStatic = e.isStatic; | |
| 1268 } else { | |
| 1269 field.isFinal = false; | |
| 1270 } | 1253 } |
| 1271 accessor.variable = field; | 1254 } |
| 1272 if (e.kind == UnlinkedExecutableKind.getter) { | 1255 // Build explicit property accessors and implicit fields. |
| 1273 field.getter = accessor; | 1256 for (var k in _kernel.procedures) { |
| 1274 } else { | 1257 bool isGetter = k.kind == kernel.ProcedureKind.Getter; |
| 1275 field.setter = accessor; | 1258 bool isSetter = k.kind == kernel.ProcedureKind.Setter; |
| 1259 if (isGetter || isSetter) { |
| 1260 var accessor = new PropertyAccessorElementImpl.forKernel(this, k); |
| 1261 explicitAccessors.add(accessor); |
| 1262 // Create or update the implicit field. |
| 1263 String fieldName = accessor.displayName; |
| 1264 FieldElementImpl field = implicitFields[fieldName]; |
| 1265 if (field == null) { |
| 1266 field = new FieldElementImpl(fieldName, -1); |
| 1267 implicitFields[fieldName] = field; |
| 1268 field.enclosingElement = this; |
| 1269 field.isSynthetic = true; |
| 1270 field.isFinal = isGetter; |
| 1271 field.isStatic = k.isStatic; |
| 1272 } else { |
| 1273 field.isFinal = false; |
| 1274 } |
| 1275 accessor.variable = field; |
| 1276 if (isGetter) { |
| 1277 field.getter = accessor; |
| 1278 } else { |
| 1279 field.setter = accessor; |
| 1280 } |
| 1281 } |
| 1282 } |
| 1283 } else { |
| 1284 // Build explicit fields and implicit property accessors. |
| 1285 for (UnlinkedVariable v in _unlinkedClass.fields) { |
| 1286 FieldElementImpl field = |
| 1287 new FieldElementImpl.forSerializedFactory(v, this); |
| 1288 explicitFields.add(field); |
| 1289 implicitAccessors.add( |
| 1290 new PropertyAccessorElementImpl_ImplicitGetter(field) |
| 1291 ..enclosingElement = this); |
| 1292 if (!field.isConst && !field.isFinal) { |
| 1293 implicitAccessors.add( |
| 1294 new PropertyAccessorElementImpl_ImplicitSetter(field) |
| 1295 ..enclosingElement = this); |
| 1296 } |
| 1297 } |
| 1298 // Build explicit property accessors and implicit fields. |
| 1299 for (UnlinkedExecutable e in _unlinkedClass.executables) { |
| 1300 if (e.kind == UnlinkedExecutableKind.getter || |
| 1301 e.kind == UnlinkedExecutableKind.setter) { |
| 1302 PropertyAccessorElementImpl accessor = |
| 1303 new PropertyAccessorElementImpl.forSerialized(e, this); |
| 1304 explicitAccessors.add(accessor); |
| 1305 // Create or update the implicit field. |
| 1306 String fieldName = accessor.displayName; |
| 1307 FieldElementImpl field = implicitFields[fieldName]; |
| 1308 if (field == null) { |
| 1309 field = new FieldElementImpl(fieldName, -1); |
| 1310 implicitFields[fieldName] = field; |
| 1311 field.enclosingElement = this; |
| 1312 field.isSynthetic = true; |
| 1313 field.isFinal = e.kind == UnlinkedExecutableKind.getter; |
| 1314 field.isStatic = e.isStatic; |
| 1315 } else { |
| 1316 field.isFinal = false; |
| 1317 } |
| 1318 accessor.variable = field; |
| 1319 if (e.kind == UnlinkedExecutableKind.getter) { |
| 1320 field.getter = accessor; |
| 1321 } else { |
| 1322 field.setter = accessor; |
| 1323 } |
| 1276 } | 1324 } |
| 1277 } | 1325 } |
| 1278 } | 1326 } |
| 1279 // Combine explicit and implicit fields and property accessors. | 1327 // Combine explicit and implicit fields and property accessors. |
| 1280 _fields = <FieldElement>[] | 1328 _fields = <FieldElement>[] |
| 1281 ..addAll(explicitFields) | 1329 ..addAll(explicitFields) |
| 1282 ..addAll(implicitFields.values); | 1330 ..addAll(implicitFields.values); |
| 1283 _accessors = <PropertyAccessorElement>[] | 1331 _accessors = <PropertyAccessorElement>[] |
| 1284 ..addAll(explicitAccessors) | 1332 ..addAll(explicitAccessors) |
| 1285 ..addAll(implicitAccessors); | 1333 ..addAll(implicitAccessors); |
| (...skipping 2973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4259 */ | 4307 */ |
| 4260 class FieldElementImpl extends PropertyInducingElementImpl | 4308 class FieldElementImpl extends PropertyInducingElementImpl |
| 4261 implements FieldElement { | 4309 implements FieldElement { |
| 4262 /** | 4310 /** |
| 4263 * Initialize a newly created synthetic field element to have the given [name] | 4311 * Initialize a newly created synthetic field element to have the given [name] |
| 4264 * at the given [offset]. | 4312 * at the given [offset]. |
| 4265 */ | 4313 */ |
| 4266 FieldElementImpl(String name, int offset) : super(name, offset); | 4314 FieldElementImpl(String name, int offset) : super(name, offset); |
| 4267 | 4315 |
| 4268 /** | 4316 /** |
| 4317 * Initialize using the given serialized information. |
| 4318 */ |
| 4319 FieldElementImpl.forKernel(ElementImpl enclosingElement, kernel.Field kernel) |
| 4320 : super.forKernel(enclosingElement, kernel); |
| 4321 |
| 4322 /** |
| 4323 * Initialize using the given serialized information. |
| 4324 */ |
| 4325 factory FieldElementImpl.forKernelFactory( |
| 4326 ClassElementImpl enclosingClass, kernel.Field kernel) { |
| 4327 // TODO(scheglov) add support for constants. |
| 4328 return new FieldElementImpl.forKernel(enclosingClass, kernel); |
| 4329 } |
| 4330 |
| 4331 /** |
| 4269 * Initialize a newly created field element to have the given [name]. | 4332 * Initialize a newly created field element to have the given [name]. |
| 4270 */ | 4333 */ |
| 4271 FieldElementImpl.forNode(Identifier name) : super.forNode(name); | 4334 FieldElementImpl.forNode(Identifier name) : super.forNode(name); |
| 4272 | 4335 |
| 4273 /** | 4336 /** |
| 4274 * Initialize using the given serialized information. | 4337 * Initialize using the given serialized information. |
| 4275 */ | 4338 */ |
| 4276 FieldElementImpl.forSerialized( | 4339 FieldElementImpl.forSerialized( |
| 4277 UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement) | 4340 UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement) |
| 4278 : super.forSerialized(unlinkedVariable, enclosingElement); | 4341 : super.forSerialized(unlinkedVariable, enclosingElement); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4313 _assertNotResynthesized(_unlinkedVariable); | 4376 _assertNotResynthesized(_unlinkedVariable); |
| 4314 setModifier(Modifier.COVARIANT, isCovariant); | 4377 setModifier(Modifier.COVARIANT, isCovariant); |
| 4315 } | 4378 } |
| 4316 | 4379 |
| 4317 @override | 4380 @override |
| 4318 bool get isEnumConstant => | 4381 bool get isEnumConstant => |
| 4319 enclosingElement != null && enclosingElement.isEnum && !isSynthetic; | 4382 enclosingElement != null && enclosingElement.isEnum && !isSynthetic; |
| 4320 | 4383 |
| 4321 @override | 4384 @override |
| 4322 bool get isStatic { | 4385 bool get isStatic { |
| 4386 if (_kernel != null) { |
| 4387 return _kernel.isStatic; |
| 4388 } |
| 4323 if (_unlinkedVariable != null) { | 4389 if (_unlinkedVariable != null) { |
| 4324 return _unlinkedVariable.isStatic; | 4390 return _unlinkedVariable.isStatic; |
| 4325 } | 4391 } |
| 4326 return hasModifier(Modifier.STATIC); | 4392 return hasModifier(Modifier.STATIC); |
| 4327 } | 4393 } |
| 4328 | 4394 |
| 4329 /** | 4395 /** |
| 4330 * Set whether this field is static. | 4396 * Set whether this field is static. |
| 4331 */ | 4397 */ |
| 4332 void set isStatic(bool isStatic) { | 4398 void set isStatic(bool isStatic) { |
| (...skipping 3773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8106 super.appendTo(buffer); | 8172 super.appendTo(buffer); |
| 8107 } | 8173 } |
| 8108 } | 8174 } |
| 8109 | 8175 |
| 8110 /** | 8176 /** |
| 8111 * A concrete implementation of a [PropertyAccessorElement]. | 8177 * A concrete implementation of a [PropertyAccessorElement]. |
| 8112 */ | 8178 */ |
| 8113 class PropertyAccessorElementImpl extends ExecutableElementImpl | 8179 class PropertyAccessorElementImpl extends ExecutableElementImpl |
| 8114 implements PropertyAccessorElement { | 8180 implements PropertyAccessorElement { |
| 8115 /** | 8181 /** |
| 8182 * The kernel of the element. |
| 8183 */ |
| 8184 final kernel.Procedure _kernelProcedure; |
| 8185 |
| 8186 /** |
| 8116 * The variable associated with this accessor. | 8187 * The variable associated with this accessor. |
| 8117 */ | 8188 */ |
| 8118 PropertyInducingElement variable; | 8189 PropertyInducingElement variable; |
| 8119 | 8190 |
| 8120 /** | 8191 /** |
| 8121 * Initialize a newly created property accessor element to have the given | 8192 * Initialize a newly created property accessor element to have the given |
| 8122 * [name] and [offset]. | 8193 * [name] and [offset]. |
| 8123 */ | 8194 */ |
| 8124 PropertyAccessorElementImpl(String name, int offset) : super(name, offset); | 8195 PropertyAccessorElementImpl(String name, int offset) |
| 8196 : _kernelProcedure = null, |
| 8197 super(name, offset); |
| 8198 |
| 8199 /** |
| 8200 * Initialize using the given kernel. |
| 8201 */ |
| 8202 PropertyAccessorElementImpl.forKernel( |
| 8203 ElementImpl enclosingElement, this._kernelProcedure) |
| 8204 : super.forKernel(enclosingElement, _kernelProcedure); |
| 8125 | 8205 |
| 8126 /** | 8206 /** |
| 8127 * Initialize a newly created property accessor element to have the given | 8207 * Initialize a newly created property accessor element to have the given |
| 8128 * [name]. | 8208 * [name]. |
| 8129 */ | 8209 */ |
| 8130 PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name); | 8210 PropertyAccessorElementImpl.forNode(Identifier name) |
| 8211 : _kernelProcedure = null, |
| 8212 super.forNode(name); |
| 8131 | 8213 |
| 8132 /** | 8214 /** |
| 8133 * Initialize using the given serialized information. | 8215 * Initialize using the given serialized information. |
| 8134 */ | 8216 */ |
| 8135 PropertyAccessorElementImpl.forSerialized( | 8217 PropertyAccessorElementImpl.forSerialized( |
| 8136 UnlinkedExecutable serializedExecutable, ElementImpl enclosingElement) | 8218 UnlinkedExecutable serializedExecutable, ElementImpl enclosingElement) |
| 8137 : super.forSerialized(serializedExecutable, enclosingElement); | 8219 : _kernelProcedure = null, |
| 8220 super.forSerialized(serializedExecutable, enclosingElement); |
| 8138 | 8221 |
| 8139 /** | 8222 /** |
| 8140 * Initialize a newly created synthetic property accessor element to be | 8223 * Initialize a newly created synthetic property accessor element to be |
| 8141 * associated with the given [variable]. | 8224 * associated with the given [variable]. |
| 8142 */ | 8225 */ |
| 8143 PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable) | 8226 PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable) |
| 8144 : super(variable.name, variable.nameOffset) { | 8227 : _kernelProcedure = null, |
| 8228 super(variable.name, variable.nameOffset) { |
| 8145 this.variable = variable; | 8229 this.variable = variable; |
| 8146 isStatic = variable.isStatic; | 8230 isStatic = variable.isStatic; |
| 8147 isSynthetic = true; | 8231 isSynthetic = true; |
| 8148 } | 8232 } |
| 8149 | 8233 |
| 8150 /** | 8234 /** |
| 8151 * Set whether this accessor is abstract. | 8235 * Set whether this accessor is abstract. |
| 8152 */ | 8236 */ |
| 8153 void set abstract(bool isAbstract) { | 8237 void set abstract(bool isAbstract) { |
| 8154 _assertNotResynthesized(serializedExecutable); | 8238 _assertNotResynthesized(serializedExecutable); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8204 | 8288 |
| 8205 @override | 8289 @override |
| 8206 String get identifier { | 8290 String get identifier { |
| 8207 String name = displayName; | 8291 String name = displayName; |
| 8208 String suffix = isGetter ? "?" : "="; | 8292 String suffix = isGetter ? "?" : "="; |
| 8209 return "$name$suffix"; | 8293 return "$name$suffix"; |
| 8210 } | 8294 } |
| 8211 | 8295 |
| 8212 @override | 8296 @override |
| 8213 bool get isGetter { | 8297 bool get isGetter { |
| 8298 if (_kernel != null) { |
| 8299 return _kernelProcedure.kind == kernel.ProcedureKind.Getter; |
| 8300 } |
| 8214 if (serializedExecutable != null) { | 8301 if (serializedExecutable != null) { |
| 8215 return serializedExecutable.kind == UnlinkedExecutableKind.getter; | 8302 return serializedExecutable.kind == UnlinkedExecutableKind.getter; |
| 8216 } | 8303 } |
| 8217 return hasModifier(Modifier.GETTER); | 8304 return hasModifier(Modifier.GETTER); |
| 8218 } | 8305 } |
| 8219 | 8306 |
| 8220 @override | 8307 @override |
| 8221 bool get isSetter { | 8308 bool get isSetter { |
| 8309 if (_kernel != null) { |
| 8310 return _kernelProcedure.kind == kernel.ProcedureKind.Setter; |
| 8311 } |
| 8222 if (serializedExecutable != null) { | 8312 if (serializedExecutable != null) { |
| 8223 return serializedExecutable.kind == UnlinkedExecutableKind.setter; | 8313 return serializedExecutable.kind == UnlinkedExecutableKind.setter; |
| 8224 } | 8314 } |
| 8225 return hasModifier(Modifier.SETTER); | 8315 return hasModifier(Modifier.SETTER); |
| 8226 } | 8316 } |
| 8227 | 8317 |
| 8228 @override | 8318 @override |
| 8229 bool get isStatic { | 8319 bool get isStatic { |
| 8320 if (_kernel != null) { |
| 8321 return _kernelProcedure.isStatic; |
| 8322 } |
| 8230 if (serializedExecutable != null) { | 8323 if (serializedExecutable != null) { |
| 8231 return serializedExecutable.isStatic || | 8324 return serializedExecutable.isStatic || |
| 8232 variable is TopLevelVariableElement; | 8325 variable is TopLevelVariableElement; |
| 8233 } | 8326 } |
| 8234 return hasModifier(Modifier.STATIC); | 8327 return hasModifier(Modifier.STATIC); |
| 8235 } | 8328 } |
| 8236 | 8329 |
| 8237 /** | 8330 /** |
| 8238 * Set whether this accessor is static. | 8331 * Set whether this accessor is static. |
| 8239 */ | 8332 */ |
| (...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9276 | 9369 |
| 9277 @override | 9370 @override |
| 9278 DartObject computeConstantValue() => null; | 9371 DartObject computeConstantValue() => null; |
| 9279 | 9372 |
| 9280 @override | 9373 @override |
| 9281 void visitChildren(ElementVisitor visitor) { | 9374 void visitChildren(ElementVisitor visitor) { |
| 9282 super.visitChildren(visitor); | 9375 super.visitChildren(visitor); |
| 9283 _initializer?.accept(visitor); | 9376 _initializer?.accept(visitor); |
| 9284 } | 9377 } |
| 9285 } | 9378 } |
| OLD | NEW |