OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 // This code was auto-generated, is not intended to be edited, and is subject to |
| 6 // significant change. Please see the README file for more information. |
| 7 |
| 8 library engine.element; |
| 9 |
| 10 import 'dart:collection'; |
| 11 import 'java_core.dart'; |
| 12 import 'java_engine.dart'; |
| 13 import 'utilities_collection.dart'; |
| 14 import 'source.dart'; |
| 15 import 'scanner.dart' show Keyword; |
| 16 import 'ast.dart'; |
| 17 import 'sdk.dart' show DartSdk; |
| 18 import 'html.dart' show XmlAttributeNode, XmlTagNode; |
| 19 import 'engine.dart' show AnalysisContext, AnalysisEngine, AnalysisException; |
| 20 import 'constant.dart' show EvaluationResultImpl; |
| 21 import 'resolver.dart'; |
| 22 import 'utilities_dart.dart'; |
| 23 |
| 24 /** |
| 25 * Information about Angular application. |
| 26 */ |
| 27 class AngularApplication { |
| 28 final Source entryPoint; |
| 29 |
| 30 final Set<Source> _librarySources; |
| 31 |
| 32 final List<AngularElement> elements; |
| 33 |
| 34 final List<Source> elementSources; |
| 35 |
| 36 AngularApplication(this.entryPoint, this._librarySources, this.elements, this.
elementSources); |
| 37 |
| 38 /** |
| 39 * Checks if this application depends on the library with the given [Source]. |
| 40 */ |
| 41 bool dependsOn(Source librarySource) => _librarySources.contains(librarySource
); |
| 42 } |
| 43 |
| 44 /** |
| 45 * The interface `AngularControllerElement` defines the Angular component descri
bed by |
| 46 * <code>Component</code> annotation. |
| 47 */ |
| 48 abstract class AngularComponentElement implements AngularHasSelectorElement, Ang
ularHasTemplateElement { |
| 49 /** |
| 50 * Return an array containing all of the properties declared by this component
. |
| 51 */ |
| 52 List<AngularPropertyElement> get properties; |
| 53 |
| 54 /** |
| 55 * Return an array containing all of the scope properties set in the implement
ation of this |
| 56 * component. |
| 57 */ |
| 58 List<AngularScopePropertyElement> get scopeProperties; |
| 59 |
| 60 /** |
| 61 * Returns the CSS file URI. |
| 62 */ |
| 63 String get styleUri; |
| 64 |
| 65 /** |
| 66 * Return the offset of the [getStyleUri] in the [getSource]. |
| 67 * |
| 68 * @return the offset of the style URI |
| 69 */ |
| 70 int get styleUriOffset; |
| 71 } |
| 72 |
| 73 /** |
| 74 * Implementation of `AngularComponentElement`. |
| 75 */ |
| 76 class AngularComponentElementImpl extends AngularHasSelectorElementImpl implemen
ts AngularComponentElement { |
| 77 /** |
| 78 * The offset of the defining <code>Component</code> annotation. |
| 79 */ |
| 80 final int _annotationOffset; |
| 81 |
| 82 /** |
| 83 * The array containing all of the properties declared by this component. |
| 84 */ |
| 85 List<AngularPropertyElement> _properties = AngularPropertyElement.EMPTY_ARRAY; |
| 86 |
| 87 /** |
| 88 * The array containing all of the scope properties set by this component. |
| 89 */ |
| 90 List<AngularScopePropertyElement> _scopeProperties = AngularScopePropertyEleme
nt.EMPTY_ARRAY; |
| 91 |
| 92 /** |
| 93 * The the CSS file URI. |
| 94 */ |
| 95 String styleUri; |
| 96 |
| 97 /** |
| 98 * The offset of the [styleUri] in the [getSource]. |
| 99 */ |
| 100 int styleUriOffset = 0; |
| 101 |
| 102 /** |
| 103 * The HTML template URI. |
| 104 */ |
| 105 String templateUri; |
| 106 |
| 107 /** |
| 108 * The HTML template source. |
| 109 */ |
| 110 Source templateSource; |
| 111 |
| 112 /** |
| 113 * The offset of the [templateUri] in the [getSource]. |
| 114 */ |
| 115 int templateUriOffset = 0; |
| 116 |
| 117 /** |
| 118 * Initialize a newly created Angular component to have the given name. |
| 119 * |
| 120 * @param name the name of this element |
| 121 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 122 * declaration of this element |
| 123 */ |
| 124 AngularComponentElementImpl(String name, int nameOffset, this._annotationOffse
t) : super(name, nameOffset); |
| 125 |
| 126 @override |
| 127 accept(ElementVisitor visitor) => visitor.visitAngularComponentElement(this); |
| 128 |
| 129 @override |
| 130 ElementKind get kind => ElementKind.ANGULAR_COMPONENT; |
| 131 |
| 132 @override |
| 133 List<AngularPropertyElement> get properties => _properties; |
| 134 |
| 135 @override |
| 136 List<AngularScopePropertyElement> get scopeProperties => _scopeProperties; |
| 137 |
| 138 /** |
| 139 * Set an array containing all of the properties declared by this component. |
| 140 * |
| 141 * @param properties the properties to set |
| 142 */ |
| 143 void set properties(List<AngularPropertyElement> properties) { |
| 144 for (AngularPropertyElement property in properties) { |
| 145 encloseElement(property as AngularPropertyElementImpl); |
| 146 } |
| 147 this._properties = properties; |
| 148 } |
| 149 |
| 150 /** |
| 151 * Set an array containing all of the scope properties declared by this compon
ent. |
| 152 * |
| 153 * @param properties the properties to set |
| 154 */ |
| 155 void set scopeProperties(List<AngularScopePropertyElement> properties) { |
| 156 for (AngularScopePropertyElement property in properties) { |
| 157 encloseElement(property as AngularScopePropertyElementImpl); |
| 158 } |
| 159 this._scopeProperties = properties; |
| 160 } |
| 161 |
| 162 @override |
| 163 void visitChildren(ElementVisitor visitor) { |
| 164 safelyVisitChildren(_properties, visitor); |
| 165 safelyVisitChildren(_scopeProperties, visitor); |
| 166 super.visitChildren(visitor); |
| 167 } |
| 168 |
| 169 @override |
| 170 String get identifier => "AngularComponent@${_annotationOffset}"; |
| 171 } |
| 172 |
| 173 /** |
| 174 * The interface `AngularControllerElement` defines the Angular controller descr
ibed by |
| 175 * <code>Controller</code> annotation. |
| 176 */ |
| 177 abstract class AngularControllerElement implements AngularHasSelectorElement { |
| 178 } |
| 179 |
| 180 /** |
| 181 * Implementation of `AngularControllerElement`. |
| 182 */ |
| 183 class AngularControllerElementImpl extends AngularHasSelectorElementImpl impleme
nts AngularControllerElement { |
| 184 /** |
| 185 * Initialize a newly created Angular controller to have the given name. |
| 186 * |
| 187 * @param name the name of this element |
| 188 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 189 * declaration of this element |
| 190 */ |
| 191 AngularControllerElementImpl(String name, int nameOffset) : super(name, nameOf
fset); |
| 192 |
| 193 @override |
| 194 accept(ElementVisitor visitor) => visitor.visitAngularControllerElement(this); |
| 195 |
| 196 @override |
| 197 ElementKind get kind => ElementKind.ANGULAR_CONTROLLER; |
| 198 } |
| 199 |
| 200 /** |
| 201 * The interface `AngularDirectiveElement` defines the Angular controller descri
bed by |
| 202 * <code>Decorator</code> annotation. |
| 203 */ |
| 204 abstract class AngularDecoratorElement implements AngularHasSelectorElement { |
| 205 /** |
| 206 * Return an array containing all of the properties declared by this directive
. |
| 207 */ |
| 208 List<AngularPropertyElement> get properties; |
| 209 |
| 210 /** |
| 211 * Checks if this directive is implemented by the class with given name. |
| 212 */ |
| 213 bool isClass(String name); |
| 214 } |
| 215 |
| 216 /** |
| 217 * Implementation of `AngularDirectiveElement`. |
| 218 */ |
| 219 class AngularDecoratorElementImpl extends AngularHasSelectorElementImpl implemen
ts AngularDecoratorElement { |
| 220 /** |
| 221 * The offset of the annotation that defines this directive. |
| 222 */ |
| 223 final int _offset; |
| 224 |
| 225 /** |
| 226 * The array containing all of the properties declared by this directive. |
| 227 */ |
| 228 List<AngularPropertyElement> _properties = AngularPropertyElement.EMPTY_ARRAY; |
| 229 |
| 230 /** |
| 231 * Initialize a newly created Angular directive to have the given name. |
| 232 * |
| 233 * @param offset the offset of the annotation that defines this directive |
| 234 */ |
| 235 AngularDecoratorElementImpl(this._offset) : super(null, -1); |
| 236 |
| 237 @override |
| 238 accept(ElementVisitor visitor) => visitor.visitAngularDirectiveElement(this); |
| 239 |
| 240 @override |
| 241 String get displayName => selector.displayName; |
| 242 |
| 243 @override |
| 244 ElementKind get kind => ElementKind.ANGULAR_DIRECTIVE; |
| 245 |
| 246 @override |
| 247 List<AngularPropertyElement> get properties => _properties; |
| 248 |
| 249 @override |
| 250 bool isClass(String name) { |
| 251 Element enclosing = enclosingElement; |
| 252 return enclosing is ClassElement && enclosing.name == name; |
| 253 } |
| 254 |
| 255 /** |
| 256 * Set an array containing all of the properties declared by this directive. |
| 257 * |
| 258 * @param properties the properties to set |
| 259 */ |
| 260 void set properties(List<AngularPropertyElement> properties) { |
| 261 for (AngularPropertyElement property in properties) { |
| 262 encloseElement(property as AngularPropertyElementImpl); |
| 263 } |
| 264 this._properties = properties; |
| 265 } |
| 266 |
| 267 @override |
| 268 void visitChildren(ElementVisitor visitor) { |
| 269 safelyVisitChildren(_properties, visitor); |
| 270 super.visitChildren(visitor); |
| 271 } |
| 272 |
| 273 @override |
| 274 String get identifier => "Decorator@${_offset}"; |
| 275 } |
| 276 |
| 277 /** |
| 278 * The interface `AngularElement` defines the behavior of objects representing i
nformation |
| 279 * about an Angular specific element. |
| 280 */ |
| 281 abstract class AngularElement implements ToolkitObjectElement { |
| 282 /** |
| 283 * An empty array of Angular elements. |
| 284 */ |
| 285 static final List<AngularElement> EMPTY_ARRAY = new List<AngularElement>(0); |
| 286 |
| 287 /** |
| 288 * Returns the [AngularApplication] this element is used in. |
| 289 * |
| 290 * @return the [AngularApplication] this element is used in |
| 291 */ |
| 292 AngularApplication get application; |
| 293 } |
| 294 |
| 295 /** |
| 296 * Implementation of `AngularElement`. |
| 297 */ |
| 298 abstract class AngularElementImpl extends ToolkitObjectElementImpl implements An
gularElement { |
| 299 /** |
| 300 * The [AngularApplication] this element is used in. |
| 301 */ |
| 302 AngularApplication _application; |
| 303 |
| 304 /** |
| 305 * Initialize a newly created Angular element to have the given name. |
| 306 * |
| 307 * @param name the name of this element |
| 308 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 309 * declaration of this element |
| 310 */ |
| 311 AngularElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 312 |
| 313 @override |
| 314 AngularApplication get application => _application; |
| 315 |
| 316 /** |
| 317 * Set the [AngularApplication] this element is used in. |
| 318 */ |
| 319 void set application(AngularApplication application) { |
| 320 this._application = application; |
| 321 } |
| 322 } |
| 323 |
| 324 /** |
| 325 * The interface `AngularFormatterElement` defines the Angular formatter describ
ed by |
| 326 * <code>Formatter</code> annotation. |
| 327 */ |
| 328 abstract class AngularFormatterElement implements AngularElement { |
| 329 } |
| 330 |
| 331 /** |
| 332 * Implementation of `AngularFormatterElement`. |
| 333 */ |
| 334 class AngularFormatterElementImpl extends AngularElementImpl implements AngularF
ormatterElement { |
| 335 /** |
| 336 * Initialize a newly created Angular formatter to have the given name. |
| 337 * |
| 338 * @param name the name of this element |
| 339 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 340 * declaration of this element |
| 341 */ |
| 342 AngularFormatterElementImpl(String name, int nameOffset) : super(name, nameOff
set); |
| 343 |
| 344 @override |
| 345 accept(ElementVisitor visitor) => visitor.visitAngularFormatterElement(this); |
| 346 |
| 347 @override |
| 348 ElementKind get kind => ElementKind.ANGULAR_FORMATTER; |
| 349 } |
| 350 |
| 351 /** |
| 352 * [AngularSelectorElement] based on presence of attribute. |
| 353 */ |
| 354 abstract class AngularHasAttributeSelectorElement implements AngularSelectorElem
ent { |
| 355 } |
| 356 |
| 357 /** |
| 358 * [AngularSelectorElement] based on presence of a class. |
| 359 */ |
| 360 abstract class AngularHasClassSelectorElement implements AngularSelectorElement
{ |
| 361 } |
| 362 |
| 363 /** |
| 364 * Implementation of [AngularSelectorElement] based on presence of a class. |
| 365 */ |
| 366 class AngularHasClassSelectorElementImpl extends AngularSelectorElementImpl impl
ements AngularHasClassSelectorElement { |
| 367 AngularHasClassSelectorElementImpl(String name, int offset) : super(name, offs
et); |
| 368 |
| 369 @override |
| 370 bool apply(XmlTagNode node) { |
| 371 XmlAttributeNode attribute = node.getAttribute("class"); |
| 372 if (attribute != null) { |
| 373 String text = attribute.text; |
| 374 if (text != null) { |
| 375 String name = this.name; |
| 376 for (String className in StringUtils.split(text)) { |
| 377 if (className == name) { |
| 378 return true; |
| 379 } |
| 380 } |
| 381 } |
| 382 } |
| 383 return false; |
| 384 } |
| 385 |
| 386 @override |
| 387 void appendTo(JavaStringBuilder builder) { |
| 388 builder.append("."); |
| 389 builder.append(name); |
| 390 } |
| 391 } |
| 392 |
| 393 /** |
| 394 * The interface `AngularElement` defines the behavior of objects representing i
nformation |
| 395 * about an Angular element which is applied conditionally using some [AngularSe
lectorElement]. |
| 396 */ |
| 397 abstract class AngularHasSelectorElement implements AngularElement { |
| 398 /** |
| 399 * Returns the selector specified for this element. |
| 400 * |
| 401 * @return the [AngularSelectorElement] specified for this element |
| 402 */ |
| 403 AngularSelectorElement get selector; |
| 404 } |
| 405 |
| 406 /** |
| 407 * Implementation of `AngularSelectorElement`. |
| 408 */ |
| 409 abstract class AngularHasSelectorElementImpl extends AngularElementImpl implemen
ts AngularHasSelectorElement { |
| 410 /** |
| 411 * The selector of this element. |
| 412 */ |
| 413 AngularSelectorElement _selector; |
| 414 |
| 415 /** |
| 416 * Initialize a newly created Angular element to have the given name. |
| 417 * |
| 418 * @param name the name of this element |
| 419 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 420 * declaration of this element |
| 421 */ |
| 422 AngularHasSelectorElementImpl(String name, int nameOffset) : super(name, nameO
ffset); |
| 423 |
| 424 @override |
| 425 AngularSelectorElement get selector => _selector; |
| 426 |
| 427 /** |
| 428 * Set the selector of this selector-based element. |
| 429 * |
| 430 * @param selector the selector to set |
| 431 */ |
| 432 void set selector(AngularSelectorElement selector) { |
| 433 encloseElement(selector as AngularSelectorElementImpl); |
| 434 this._selector = selector; |
| 435 } |
| 436 |
| 437 @override |
| 438 void visitChildren(ElementVisitor visitor) { |
| 439 safelyVisitChild(_selector, visitor); |
| 440 super.visitChildren(visitor); |
| 441 } |
| 442 } |
| 443 |
| 444 /** |
| 445 * The interface `AngularHasTemplateElement` defines common behavior for |
| 446 * [AngularElement] that have template URI / [Source]. |
| 447 */ |
| 448 abstract class AngularHasTemplateElement implements AngularElement { |
| 449 /** |
| 450 * Returns the HTML template [Source], `null` if not resolved. |
| 451 */ |
| 452 Source get templateSource; |
| 453 |
| 454 /** |
| 455 * Returns the HTML template URI. |
| 456 */ |
| 457 String get templateUri; |
| 458 |
| 459 /** |
| 460 * Return the offset of the [getTemplateUri] in the [getSource]. |
| 461 * |
| 462 * @return the offset of the template URI |
| 463 */ |
| 464 int get templateUriOffset; |
| 465 } |
| 466 |
| 467 /** |
| 468 * The interface `AngularPropertyElement` defines a single property in |
| 469 * [AngularComponentElement]. |
| 470 */ |
| 471 abstract class AngularPropertyElement implements AngularElement { |
| 472 /** |
| 473 * An empty array of property elements. |
| 474 */ |
| 475 static final List<AngularPropertyElement> EMPTY_ARRAY = []; |
| 476 |
| 477 /** |
| 478 * Returns the field this property is mapped to. |
| 479 * |
| 480 * @return the field this property is mapped to. |
| 481 */ |
| 482 FieldElement get field; |
| 483 |
| 484 /** |
| 485 * Return the offset of the field name of this property in the property map, o
r `-1` if |
| 486 * property was created using annotation on [FieldElement]. |
| 487 * |
| 488 * @return the offset of the field name of this property |
| 489 */ |
| 490 int get fieldNameOffset; |
| 491 |
| 492 /** |
| 493 * Returns the kind of this property. |
| 494 * |
| 495 * @return the kind of this property |
| 496 */ |
| 497 AngularPropertyKind get propertyKind; |
| 498 } |
| 499 |
| 500 /** |
| 501 * Implementation of `AngularPropertyElement`. |
| 502 */ |
| 503 class AngularPropertyElementImpl extends AngularElementImpl implements AngularPr
opertyElement { |
| 504 /** |
| 505 * The [FieldElement] to which this property is bound. |
| 506 */ |
| 507 FieldElement field; |
| 508 |
| 509 /** |
| 510 * The offset of the field name in the property map. |
| 511 */ |
| 512 int fieldNameOffset = -1; |
| 513 |
| 514 AngularPropertyKind propertyKind; |
| 515 |
| 516 /** |
| 517 * Initialize a newly created Angular property to have the given name. |
| 518 * |
| 519 * @param name the name of this element |
| 520 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 521 * declaration of this element |
| 522 */ |
| 523 AngularPropertyElementImpl(String name, int nameOffset) : super(name, nameOffs
et); |
| 524 |
| 525 @override |
| 526 accept(ElementVisitor visitor) => visitor.visitAngularPropertyElement(this); |
| 527 |
| 528 @override |
| 529 ElementKind get kind => ElementKind.ANGULAR_PROPERTY; |
| 530 } |
| 531 |
| 532 /** |
| 533 * The enumeration `AngularPropertyKind` defines the different kinds of property
bindings. |
| 534 */ |
| 535 class AngularPropertyKind extends Enum<AngularPropertyKind> { |
| 536 /** |
| 537 * `@` - Map the DOM attribute string. The attribute string will be taken lite
rally or |
| 538 * interpolated if it contains binding {{}} syntax and assigned to the express
ion. (cost: 0 |
| 539 * watches) |
| 540 */ |
| 541 static const AngularPropertyKind ATTR = const AngularPropertyKind('ATTR', 0); |
| 542 |
| 543 /** |
| 544 * `&` - Treat the DOM attribute value as an expression. Assign a closure func
tion into the field. |
| 545 * This allows the component to control the invocation of the closure. This is
useful for passing |
| 546 * expressions into controllers which act like callbacks. (cost: 0 watches) |
| 547 */ |
| 548 static const AngularPropertyKind CALLBACK = const AngularPropertyKind('CALLBAC
K', 1); |
| 549 |
| 550 /** |
| 551 * `=>` - Treat the DOM attribute value as an expression. Set up a watch, whic
h will read the |
| 552 * expression in the attribute and assign the value to destination expression.
(cost: 1 watch) |
| 553 */ |
| 554 static const AngularPropertyKind ONE_WAY = const AngularPropertyKind('ONE_WAY'
, 2); |
| 555 |
| 556 /** |
| 557 * `=>!` - Treat the DOM attribute value as an expression. Set up a one time w
atch on expression. |
| 558 * Once the expression turns not null it will no longer update. (cost: 1 watch
es until not null, |
| 559 * then 0 watches) |
| 560 */ |
| 561 static const AngularPropertyKind ONE_WAY_ONE_TIME = const AngularPropertyKind(
'ONE_WAY_ONE_TIME', 3); |
| 562 |
| 563 /** |
| 564 * `<=>` - Treat the DOM attribute value as an expression. Set up a watch on b
oth outside as well |
| 565 * as component scope to keep the source and destination in sync. (cost: 2 wat
ches) |
| 566 */ |
| 567 static const AngularPropertyKind TWO_WAY = const AngularPropertyKind_TWO_WAY('
TWO_WAY', 4); |
| 568 |
| 569 static const List<AngularPropertyKind> values = const [ATTR, CALLBACK, ONE_WAY
, ONE_WAY_ONE_TIME, TWO_WAY]; |
| 570 |
| 571 /** |
| 572 * Returns `true` if property of this kind calls field getter. |
| 573 */ |
| 574 bool callsGetter() => false; |
| 575 |
| 576 /** |
| 577 * Returns `true` if property of this kind calls field setter. |
| 578 */ |
| 579 bool callsSetter() => true; |
| 580 |
| 581 const AngularPropertyKind(String name, int ordinal) : super(name, ordinal); |
| 582 } |
| 583 |
| 584 class AngularPropertyKind_TWO_WAY extends AngularPropertyKind { |
| 585 const AngularPropertyKind_TWO_WAY(String name, int ordinal) : super(name, ordi
nal); |
| 586 |
| 587 @override |
| 588 bool callsGetter() => true; |
| 589 } |
| 590 |
| 591 /** |
| 592 * The interface `AngularScopeVariableElement` defines the Angular <code>Scope</
code> |
| 593 * property. They are created for every <code>scope['property'] = value;</code>
code snippet. |
| 594 */ |
| 595 abstract class AngularScopePropertyElement implements AngularElement { |
| 596 /** |
| 597 * An empty array of scope property elements. |
| 598 */ |
| 599 static final List<AngularScopePropertyElement> EMPTY_ARRAY = []; |
| 600 |
| 601 /** |
| 602 * Returns the type of this property, not `null`, maybe <code>dynamic</code>. |
| 603 * |
| 604 * @return the type of this property. |
| 605 */ |
| 606 DartType get type; |
| 607 } |
| 608 |
| 609 /** |
| 610 * Implementation of `AngularScopePropertyElement`. |
| 611 */ |
| 612 class AngularScopePropertyElementImpl extends AngularElementImpl implements Angu
larScopePropertyElement { |
| 613 /** |
| 614 * The type of the property |
| 615 */ |
| 616 final DartType type; |
| 617 |
| 618 /** |
| 619 * Initialize a newly created Angular scope property to have the given name. |
| 620 * |
| 621 * @param name the name of this element |
| 622 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 623 * declaration of this element |
| 624 */ |
| 625 AngularScopePropertyElementImpl(String name, int nameOffset, this.type) : supe
r(name, nameOffset); |
| 626 |
| 627 @override |
| 628 accept(ElementVisitor visitor) => visitor.visitAngularScopePropertyElement(thi
s); |
| 629 |
| 630 @override |
| 631 ElementKind get kind => ElementKind.ANGULAR_SCOPE_PROPERTY; |
| 632 } |
| 633 |
| 634 /** |
| 635 * [AngularSelectorElement] is used to decide when Angular object should be appl
ied. |
| 636 * |
| 637 * This class is an [Element] to support renaming component tag names, which are
identifiers |
| 638 * in selectors. |
| 639 */ |
| 640 abstract class AngularSelectorElement implements AngularElement { |
| 641 /** |
| 642 * Checks if the given [XmlTagNode] matches this selector. |
| 643 * |
| 644 * @param node the [XmlTagNode] to check |
| 645 * @return `true` if the given [XmlTagNode] matches, or `false` otherwise |
| 646 */ |
| 647 bool apply(XmlTagNode node); |
| 648 } |
| 649 |
| 650 /** |
| 651 * Implementation of `AngularFormatterElement`. |
| 652 */ |
| 653 abstract class AngularSelectorElementImpl extends AngularElementImpl implements
AngularSelectorElement { |
| 654 /** |
| 655 * Initialize a newly created Angular selector to have the given name. |
| 656 * |
| 657 * @param name the name of this element |
| 658 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 659 * declaration of this element |
| 660 */ |
| 661 AngularSelectorElementImpl(String name, int nameOffset) : super(name, nameOffs
et); |
| 662 |
| 663 @override |
| 664 accept(ElementVisitor visitor) => visitor.visitAngularSelectorElement(this); |
| 665 |
| 666 @override |
| 667 ElementKind get kind => ElementKind.ANGULAR_SELECTOR; |
| 668 } |
| 669 |
| 670 /** |
| 671 * [AngularSelectorElement] based on tag name. |
| 672 */ |
| 673 abstract class AngularTagSelectorElement implements AngularSelectorElement { |
| 674 } |
| 675 |
| 676 /** |
| 677 * Implementation of [AngularSelectorElement] based on tag name. |
| 678 */ |
| 679 class AngularTagSelectorElementImpl extends AngularSelectorElementImpl implement
s AngularTagSelectorElement { |
| 680 AngularTagSelectorElementImpl(String name, int offset) : super(name, offset); |
| 681 |
| 682 @override |
| 683 bool apply(XmlTagNode node) { |
| 684 String tagName = name; |
| 685 return node.tag == tagName; |
| 686 } |
| 687 |
| 688 @override |
| 689 AngularApplication get application => (enclosingElement as AngularElementImpl)
.application; |
| 690 } |
| 691 |
| 692 /** |
| 693 * The interface `AngularViewElement` defines the Angular view defined using inv
ocation like |
| 694 * <code>view('views/create.html')</code>. |
| 695 */ |
| 696 abstract class AngularViewElement implements AngularHasTemplateElement { |
| 697 /** |
| 698 * An empty array of view elements. |
| 699 */ |
| 700 static final List<AngularViewElement> EMPTY_ARRAY = new List<AngularViewElemen
t>(0); |
| 701 } |
| 702 |
| 703 /** |
| 704 * Implementation of `AngularViewElement`. |
| 705 */ |
| 706 class AngularViewElementImpl extends AngularElementImpl implements AngularViewEl
ement { |
| 707 /** |
| 708 * The HTML template URI. |
| 709 */ |
| 710 final String templateUri; |
| 711 |
| 712 /** |
| 713 * The offset of the [templateUri] in the [getSource]. |
| 714 */ |
| 715 final int templateUriOffset; |
| 716 |
| 717 /** |
| 718 * The HTML template source. |
| 719 */ |
| 720 Source templateSource; |
| 721 |
| 722 /** |
| 723 * Initialize a newly created Angular view. |
| 724 */ |
| 725 AngularViewElementImpl(this.templateUri, this.templateUriOffset) : super(null,
-1); |
| 726 |
| 727 @override |
| 728 accept(ElementVisitor visitor) => visitor.visitAngularViewElement(this); |
| 729 |
| 730 @override |
| 731 ElementKind get kind => ElementKind.ANGULAR_VIEW; |
| 732 |
| 733 @override |
| 734 String get identifier => "AngularView@${templateUriOffset}"; |
| 735 } |
| 736 |
| 737 /** |
| 738 * For AST nodes that could be in both the getter and setter contexts ([IndexExp
ression]s and |
| 739 * [SimpleIdentifier]s), the additional resolved elements are stored in the AST
node, in an |
| 740 * [AuxiliaryElements]. Since resolved elements are either statically resolved o
r resolved |
| 741 * using propagated type information, this class is a wrapper for a pair of |
| 742 * [ExecutableElement]s, not just a single [ExecutableElement]. |
| 743 */ |
| 744 class AuxiliaryElements { |
| 745 /** |
| 746 * The element based on propagated type information, or `null` if the AST stru
cture has not |
| 747 * been resolved or if this identifier could not be resolved. |
| 748 */ |
| 749 final ExecutableElement propagatedElement; |
| 750 |
| 751 /** |
| 752 * The element associated with this identifier based on static type informatio
n, or `null` |
| 753 * if the AST structure has not been resolved or if this identifier could not
be resolved. |
| 754 */ |
| 755 final ExecutableElement staticElement; |
| 756 |
| 757 /** |
| 758 * Create the [AuxiliaryElements] with a static and propagated [ExecutableElem
ent]. |
| 759 * |
| 760 * @param staticElement the static element |
| 761 * @param propagatedElement the propagated element |
| 762 */ |
| 763 AuxiliaryElements(this.staticElement, this.propagatedElement); |
| 764 } |
| 765 |
| 766 /** |
| 767 * The unique instance of the class `BottomTypeImpl` implements the type `bottom
`. |
| 768 */ |
| 769 class BottomTypeImpl extends TypeImpl { |
| 770 /** |
| 771 * The unique instance of this class. |
| 772 */ |
| 773 static BottomTypeImpl _INSTANCE = new BottomTypeImpl(); |
| 774 |
| 775 /** |
| 776 * Return the unique instance of this class. |
| 777 * |
| 778 * @return the unique instance of this class |
| 779 */ |
| 780 static BottomTypeImpl get instance => _INSTANCE; |
| 781 |
| 782 /** |
| 783 * Prevent the creation of instances of this class. |
| 784 */ |
| 785 BottomTypeImpl() : super(null, "<bottom>"); |
| 786 |
| 787 @override |
| 788 bool operator ==(Object object) => identical(object, this); |
| 789 |
| 790 @override |
| 791 int get hashCode => 0; |
| 792 |
| 793 @override |
| 794 bool get isBottom => true; |
| 795 |
| 796 @override |
| 797 bool isSupertypeOf(DartType type) => false; |
| 798 |
| 799 @override |
| 800 BottomTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> parame
terTypes) => this; |
| 801 |
| 802 @override |
| 803 bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => id
entical(object, this); |
| 804 |
| 805 @override |
| 806 bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_
TypePair> visitedTypePairs) => true; |
| 807 |
| 808 @override |
| 809 bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePair
s) => true; |
| 810 } |
| 811 |
| 812 /** |
| 813 * The interface `ClassElement` defines the behavior of elements that represent
a class. |
| 814 */ |
| 815 abstract class ClassElement implements Element { |
| 816 /** |
| 817 * Return an array containing all of the accessors (getters and setters) decla
red in this class. |
| 818 * |
| 819 * @return the accessors declared in this class |
| 820 */ |
| 821 List<PropertyAccessorElement> get accessors; |
| 822 |
| 823 /** |
| 824 * Return an array containing all the supertypes defined for this class and it
s supertypes. This |
| 825 * includes superclasses, mixins and interfaces. |
| 826 * |
| 827 * @return all the supertypes of this class, including mixins |
| 828 */ |
| 829 List<InterfaceType> get allSupertypes; |
| 830 |
| 831 /** |
| 832 * Return an array containing all of the constructors declared in this class. |
| 833 * |
| 834 * @return the constructors declared in this class |
| 835 */ |
| 836 List<ConstructorElement> get constructors; |
| 837 |
| 838 /** |
| 839 * Return the field (synthetic or explicit) defined in this class that has the
given name, or |
| 840 * `null` if this class does not define a field with the given name. |
| 841 * |
| 842 * @param fieldName the name of the field to be returned |
| 843 * @return the field with the given name that is defined in this class |
| 844 */ |
| 845 FieldElement getField(String fieldName); |
| 846 |
| 847 /** |
| 848 * Return an array containing all of the fields declared in this class. |
| 849 * |
| 850 * @return the fields declared in this class |
| 851 */ |
| 852 List<FieldElement> get fields; |
| 853 |
| 854 /** |
| 855 * Return the element representing the getter with the given name that is decl
ared in this class, |
| 856 * or `null` if this class does not declare a getter with the given name. |
| 857 * |
| 858 * @param getterName the name of the getter to be returned |
| 859 * @return the getter declared in this class with the given name |
| 860 */ |
| 861 PropertyAccessorElement getGetter(String getterName); |
| 862 |
| 863 /** |
| 864 * Return an array containing all of the interfaces that are implemented by th
is class. |
| 865 * |
| 866 * <b>Note:</b> Because the element model represents the state of the code, it
is possible for it |
| 867 * to be semantically invalid. In particular, it is not safe to assume that th
e inheritance |
| 868 * structure of a class does not contain a cycle. Clients that traverse the in
heritance structure |
| 869 * must explicitly guard against infinite loops. |
| 870 * |
| 871 * @return the interfaces that are implemented by this class |
| 872 */ |
| 873 List<InterfaceType> get interfaces; |
| 874 |
| 875 /** |
| 876 * Return the element representing the method with the given name that is decl
ared in this class, |
| 877 * or `null` if this class does not declare a method with the given name. |
| 878 * |
| 879 * @param methodName the name of the method to be returned |
| 880 * @return the method declared in this class with the given name |
| 881 */ |
| 882 MethodElement getMethod(String methodName); |
| 883 |
| 884 /** |
| 885 * Return an array containing all of the methods declared in this class. |
| 886 * |
| 887 * @return the methods declared in this class |
| 888 */ |
| 889 List<MethodElement> get methods; |
| 890 |
| 891 /** |
| 892 * Return an array containing all of the mixins that are applied to the class
being extended in |
| 893 * order to derive the superclass of this class. |
| 894 * |
| 895 * <b>Note:</b> Because the element model represents the state of the code, it
is possible for it |
| 896 * to be semantically invalid. In particular, it is not safe to assume that th
e inheritance |
| 897 * structure of a class does not contain a cycle. Clients that traverse the in
heritance structure |
| 898 * must explicitly guard against infinite loops. |
| 899 * |
| 900 * @return the mixins that are applied to derive the superclass of this class |
| 901 */ |
| 902 List<InterfaceType> get mixins; |
| 903 |
| 904 /** |
| 905 * Return the named constructor declared in this class with the given name, or
`null` if |
| 906 * this class does not declare a named constructor with the given name. |
| 907 * |
| 908 * @param name the name of the constructor to be returned |
| 909 * @return the element representing the specified constructor |
| 910 */ |
| 911 ConstructorElement getNamedConstructor(String name); |
| 912 |
| 913 /** |
| 914 * Return the resolved [ClassDeclaration] node that declares this [ClassElemen
t]. |
| 915 * |
| 916 * This method is expensive, because resolved AST might be evicted from cache,
so parsing and |
| 917 * resolving will be performed. |
| 918 * |
| 919 * @return the resolved [ClassDeclaration], not `null`. |
| 920 */ |
| 921 @override |
| 922 ClassDeclaration get node; |
| 923 |
| 924 /** |
| 925 * Return the element representing the setter with the given name that is decl
ared in this class, |
| 926 * or `null` if this class does not declare a setter with the given name. |
| 927 * |
| 928 * @param setterName the name of the getter to be returned |
| 929 * @return the setter declared in this class with the given name |
| 930 */ |
| 931 PropertyAccessorElement getSetter(String setterName); |
| 932 |
| 933 /** |
| 934 * Return the superclass of this class, or `null` if the class represents the
class |
| 935 * 'Object'. All other classes will have a non-`null` superclass. If the super
class was not |
| 936 * explicitly declared then the implicit superclass 'Object' will be returned. |
| 937 * |
| 938 * <b>Note:</b> Because the element model represents the state of the code, it
is possible for it |
| 939 * to be semantically invalid. In particular, it is not safe to assume that th
e inheritance |
| 940 * structure of a class does not contain a cycle. Clients that traverse the in
heritance structure |
| 941 * must explicitly guard against infinite loops. |
| 942 * |
| 943 * @return the superclass of this class |
| 944 */ |
| 945 InterfaceType get supertype; |
| 946 |
| 947 /** |
| 948 * Return an array containing all of the toolkit specific objects associated w
ith this class. The |
| 949 * array will be empty if the class does not have any toolkit specific objects
or if the |
| 950 * compilation unit containing the class has not yet had toolkit references re
solved. |
| 951 * |
| 952 * @return the toolkit objects associated with this class |
| 953 */ |
| 954 List<ToolkitObjectElement> get toolkitObjects; |
| 955 |
| 956 /** |
| 957 * Return the type defined by the class. |
| 958 * |
| 959 * @return the type defined by the class |
| 960 */ |
| 961 InterfaceType get type; |
| 962 |
| 963 /** |
| 964 * Return an array containing all of the type parameters declared for this cla
ss. |
| 965 * |
| 966 * @return the type parameters declared for this class |
| 967 */ |
| 968 List<TypeParameterElement> get typeParameters; |
| 969 |
| 970 /** |
| 971 * Return the unnamed constructor declared in this class, or `null` if this cl
ass does not |
| 972 * declare an unnamed constructor but does declare named constructors. The ret
urned constructor |
| 973 * will be synthetic if this class does not declare any constructors, in which
case it will |
| 974 * represent the default constructor for the class. |
| 975 * |
| 976 * @return the unnamed constructor defined in this class |
| 977 */ |
| 978 ConstructorElement get unnamedConstructor; |
| 979 |
| 980 /** |
| 981 * Return `true` if this class or its superclass declares a non-final instance
field. |
| 982 * |
| 983 * @return `true` if this class or its superclass declares a non-final instanc
e field |
| 984 */ |
| 985 bool get hasNonFinalField; |
| 986 |
| 987 /** |
| 988 * Return `true` if this class has reference to super (so, for example, cannot
be used as a |
| 989 * mixin). |
| 990 * |
| 991 * @return `true` if this class has reference to super |
| 992 */ |
| 993 bool get hasReferenceToSuper; |
| 994 |
| 995 /** |
| 996 * Return `true` if this class declares a static member. |
| 997 * |
| 998 * @return `true` if this class declares a static member |
| 999 */ |
| 1000 bool get hasStaticMember; |
| 1001 |
| 1002 /** |
| 1003 * Return `true` if this class is abstract. A class is abstract if it has an e
xplicit |
| 1004 * `abstract` modifier. Note, that this definition of <i>abstract</i> is diffe
rent from |
| 1005 * <i>has unimplemented members</i>. |
| 1006 * |
| 1007 * @return `true` if this class is abstract |
| 1008 */ |
| 1009 bool get isAbstract; |
| 1010 |
| 1011 /** |
| 1012 * Return `true` if this class is defined by an enum declaration. |
| 1013 * |
| 1014 * @return `true` if this class is defined by an enum declaration |
| 1015 */ |
| 1016 bool get isEnum; |
| 1017 |
| 1018 /** |
| 1019 * Return `true` if this class [isProxy], or if it inherits the proxy annotati
on |
| 1020 * from a supertype. |
| 1021 * |
| 1022 * @return `true` if this class defines or inherits a proxy |
| 1023 */ |
| 1024 bool get isOrInheritsProxy; |
| 1025 |
| 1026 /** |
| 1027 * Return `true` if this element has an annotation of the form '@proxy'. |
| 1028 * |
| 1029 * @return `true` if this element defines a proxy |
| 1030 */ |
| 1031 bool get isProxy; |
| 1032 |
| 1033 /** |
| 1034 * Return `true` if this class is defined by a typedef construct. |
| 1035 * |
| 1036 * @return `true` if this class is defined by a typedef construct |
| 1037 */ |
| 1038 bool get isTypedef; |
| 1039 |
| 1040 /** |
| 1041 * Return `true` if this class can validly be used as a mixin when defining an
other class. |
| 1042 * The behavior of this method is defined by the Dart Language Specification i
n section 9: |
| 1043 * <blockquote>It is a compile-time error if a declared or derived mixin refer
s to super. It is a |
| 1044 * compile-time error if a declared or derived mixin explicitly declares a con
structor. It is a |
| 1045 * compile-time error if a mixin is derived from a class whose superclass is n
ot |
| 1046 * Object.</blockquote> |
| 1047 * |
| 1048 * @return `true` if this class can validly be used as a mixin |
| 1049 */ |
| 1050 bool get isValidMixin; |
| 1051 |
| 1052 /** |
| 1053 * Return the element representing the method that results from looking up the
given method in |
| 1054 * this class with respect to the given library, ignoring abstract methods, or
`null` if the |
| 1055 * look up fails. The behavior of this method is defined by the Dart Language
Specification in |
| 1056 * section 12.15.1: <blockquote> The result of looking up method <i>m</i> in c
lass <i>C</i> with |
| 1057 * respect to library <i>L</i> is: |
| 1058 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible
to <i>L</i>, then |
| 1059 * that method is the result of the lookup. Otherwise, if <i>C</i> has a super
class <i>S</i>, then |
| 1060 * the result of the lookup is the result of looking up method <i>m</i> in <i>
S</i> with respect |
| 1061 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 1062 * </blockquote> |
| 1063 * |
| 1064 * @param methodName the name of the method being looked up |
| 1065 * @param library the library with respect to which the lookup is being perfor
med |
| 1066 * @return the result of looking up the given method in this class with respec
t to the given |
| 1067 * library |
| 1068 */ |
| 1069 MethodElement lookUpConcreteMethod(String methodName, LibraryElement library); |
| 1070 |
| 1071 /** |
| 1072 * Return the element representing the getter that results from looking up the
given getter in |
| 1073 * this class with respect to the given library, or `null` if the look up fail
s. The |
| 1074 * behavior of this method is defined by the Dart Language Specification in se
ction 12.15.1: |
| 1075 * <blockquote>The result of looking up getter (respectively setter) <i>m</i>
in class <i>C</i> |
| 1076 * with respect to library <i>L</i> is: |
| 1077 * * If <i>C</i> declares an instance getter (respectively setter) named <i>m<
/i> that is |
| 1078 * accessible to <i>L</i>, then that getter (respectively setter) is the resul
t of the lookup. |
| 1079 * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lo
okup is the result |
| 1080 * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respec
t to <i>L</i>. |
| 1081 * Otherwise, we say that the lookup has failed. |
| 1082 * </blockquote> |
| 1083 * |
| 1084 * @param getterName the name of the getter being looked up |
| 1085 * @param library the library with respect to which the lookup is being perfor
med |
| 1086 * @return the result of looking up the given getter in this class with respec
t to the given |
| 1087 * library |
| 1088 */ |
| 1089 PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library
); |
| 1090 |
| 1091 /** |
| 1092 * Return the element representing the getter that results from looking up the
given getter in the |
| 1093 * superclass of this class with respect to the given library, ignoring abstra
ct getters, or |
| 1094 * `null` if the look up fails. The behavior of this method is defined by the
Dart Language |
| 1095 * Specification in section 12.15.1: <blockquote>The result of looking up gett
er (respectively |
| 1096 * setter) <i>m</i> in class <i>C</i> with respect to library <i>L</i> is: |
| 1097 * * If <i>C</i> declares an instance getter (respectively setter) named <i>m<
/i> that is |
| 1098 * accessible to <i>L</i>, then that getter (respectively setter) is the resul
t of the lookup. |
| 1099 * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lo
okup is the result |
| 1100 * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respec
t to <i>L</i>. |
| 1101 * Otherwise, we say that the lookup has failed. |
| 1102 * </blockquote> |
| 1103 * |
| 1104 * @param getterName the name of the getter being looked up |
| 1105 * @param library the library with respect to which the lookup is being perfor
med |
| 1106 * @return the result of looking up the given getter in this class with respec
t to the given |
| 1107 * library |
| 1108 */ |
| 1109 PropertyAccessorElement lookUpInheritedConcreteGetter(String getterName, Libra
ryElement library); |
| 1110 |
| 1111 /** |
| 1112 * Return the element representing the method that results from looking up the
given method in the |
| 1113 * superclass of this class with respect to the given library, ignoring abstra
ct methods, or |
| 1114 * `null` if the look up fails. The behavior of this method is defined by the
Dart Language |
| 1115 * Specification in section 12.15.1: <blockquote> The result of looking up met
hod <i>m</i> in |
| 1116 * class <i>C</i> with respect to library <i>L</i> is: |
| 1117 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible
to <i>L</i>, then |
| 1118 * that method is the result of the lookup. Otherwise, if <i>C</i> has a super
class <i>S</i>, then |
| 1119 * the result of the lookup is the result of looking up method <i>m</i> in <i>
S</i> with respect |
| 1120 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 1121 * </blockquote> |
| 1122 * |
| 1123 * @param methodName the name of the method being looked up |
| 1124 * @param library the library with respect to which the lookup is being perfor
med |
| 1125 * @return the result of looking up the given method in the superclass of this
class with respect |
| 1126 * to the given library |
| 1127 */ |
| 1128 MethodElement lookUpInheritedConcreteMethod(String methodName, LibraryElement
library); |
| 1129 |
| 1130 /** |
| 1131 * Return the element representing the setter that results from looking up the
given setter in the |
| 1132 * superclass of this class with respect to the given library, ignoring abstra
ct setters, or |
| 1133 * `null` if the look up fails. The behavior of this method is defined by the
Dart Language |
| 1134 * Specification in section 12.16: <blockquote> The result of looking up gette
r (respectively |
| 1135 * setter) <i>m</i> in class <i>C</i> with respect to library <i>L</i> is: |
| 1136 * * If <i>C</i> declares an instance getter (respectively setter) named <i>m<
/i> that is |
| 1137 * accessible to <i>L</i>, then that getter (respectively setter) is the resul
t of the lookup. |
| 1138 * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lo
okup is the result |
| 1139 * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respec
t to <i>L</i>. |
| 1140 * Otherwise, we say that the lookup has failed. |
| 1141 * </blockquote> |
| 1142 * |
| 1143 * @param setterName the name of the setter being looked up |
| 1144 * @param library the library with respect to which the lookup is being perfor
med |
| 1145 * @return the result of looking up the given setter in this class with respec
t to the given |
| 1146 * library |
| 1147 */ |
| 1148 PropertyAccessorElement lookUpInheritedConcreteSetter(String setterName, Libra
ryElement library); |
| 1149 |
| 1150 /** |
| 1151 * Return the element representing the method that results from looking up the
given method in the |
| 1152 * superclass of this class with respect to the given library, or `null` if th
e look up |
| 1153 * fails. The behavior of this method is defined by the Dart Language Specific
ation in section |
| 1154 * 12.15.1: <blockquote> The result of looking up method <i>m</i> in class <i>
C</i> with respect |
| 1155 * to library <i>L</i> is: |
| 1156 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible
to <i>L</i>, then |
| 1157 * that method is the result of the lookup. Otherwise, if <i>C</i> has a super
class <i>S</i>, then |
| 1158 * the result of the lookup is the result of looking up method <i>m</i> in <i>
S</i> with respect |
| 1159 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 1160 * </blockquote> |
| 1161 * |
| 1162 * @param methodName the name of the method being looked up |
| 1163 * @param library the library with respect to which the lookup is being perfor
med |
| 1164 * @return the result of looking up the given method in the superclass of this
class with respect |
| 1165 * to the given library |
| 1166 */ |
| 1167 MethodElement lookUpInheritedMethod(String methodName, LibraryElement library)
; |
| 1168 |
| 1169 /** |
| 1170 * Return the element representing the method that results from looking up the
given method in |
| 1171 * this class with respect to the given library, or `null` if the look up fail
s. The |
| 1172 * behavior of this method is defined by the Dart Language Specification in se
ction 12.15.1: |
| 1173 * <blockquote> The result of looking up method <i>m</i> in class <i>C</i> wit
h respect to library |
| 1174 * <i>L</i> is: |
| 1175 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible
to <i>L</i>, then |
| 1176 * that method is the result of the lookup. Otherwise, if <i>C</i> has a super
class <i>S</i>, then |
| 1177 * the result of the lookup is the result of looking up method <i>m</i> in <i>
S</i> with respect |
| 1178 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 1179 * </blockquote> |
| 1180 * |
| 1181 * @param methodName the name of the method being looked up |
| 1182 * @param library the library with respect to which the lookup is being perfor
med |
| 1183 * @return the result of looking up the given method in this class with respec
t to the given |
| 1184 * library |
| 1185 */ |
| 1186 MethodElement lookUpMethod(String methodName, LibraryElement library); |
| 1187 |
| 1188 /** |
| 1189 * Return the element representing the setter that results from looking up the
given setter in |
| 1190 * this class with respect to the given library, or `null` if the look up fail
s. The |
| 1191 * behavior of this method is defined by the Dart Language Specification in se
ction 12.16: |
| 1192 * <blockquote> The result of looking up getter (respectively setter) <i>m</i>
in class <i>C</i> |
| 1193 * with respect to library <i>L</i> is: |
| 1194 * * If <i>C</i> declares an instance getter (respectively setter) named <i>m<
/i> that is |
| 1195 * accessible to <i>L</i>, then that getter (respectively setter) is the resul
t of the lookup. |
| 1196 * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lo
okup is the result |
| 1197 * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respec
t to <i>L</i>. |
| 1198 * Otherwise, we say that the lookup has failed. |
| 1199 * </blockquote> |
| 1200 * |
| 1201 * @param setterName the name of the setter being looked up |
| 1202 * @param library the library with respect to which the lookup is being perfor
med |
| 1203 * @return the result of looking up the given setter in this class with respec
t to the given |
| 1204 * library |
| 1205 */ |
| 1206 PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library
); |
| 1207 } |
| 1208 |
| 1209 /** |
| 1210 * Instances of the class `ClassElementImpl` implement a `ClassElement`. |
| 1211 */ |
| 1212 class ClassElementImpl extends ElementImpl implements ClassElement { |
| 1213 /** |
| 1214 * An array containing all of the accessors (getters and setters) contained in
this class. |
| 1215 */ |
| 1216 List<PropertyAccessorElement> _accessors = PropertyAccessorElementImpl.EMPTY_A
RRAY; |
| 1217 |
| 1218 /** |
| 1219 * An array containing all of the constructors contained in this class. |
| 1220 */ |
| 1221 List<ConstructorElement> _constructors = ConstructorElementImpl.EMPTY_ARRAY; |
| 1222 |
| 1223 /** |
| 1224 * An array containing all of the fields contained in this class. |
| 1225 */ |
| 1226 List<FieldElement> _fields = FieldElementImpl.EMPTY_ARRAY; |
| 1227 |
| 1228 /** |
| 1229 * An array containing all of the mixins that are applied to the class being e
xtended in order to |
| 1230 * derive the superclass of this class. |
| 1231 */ |
| 1232 List<InterfaceType> mixins = InterfaceType.EMPTY_ARRAY; |
| 1233 |
| 1234 /** |
| 1235 * An array containing all of the interfaces that are implemented by this clas
s. |
| 1236 */ |
| 1237 List<InterfaceType> interfaces = InterfaceType.EMPTY_ARRAY; |
| 1238 |
| 1239 /** |
| 1240 * An array containing all of the methods contained in this class. |
| 1241 */ |
| 1242 List<MethodElement> _methods = MethodElementImpl.EMPTY_ARRAY; |
| 1243 |
| 1244 /** |
| 1245 * The superclass of the class, or `null` if the class does not have an explic
it superclass. |
| 1246 */ |
| 1247 InterfaceType supertype; |
| 1248 |
| 1249 /** |
| 1250 * An array containing all of the toolkit objects attached to this class. |
| 1251 */ |
| 1252 List<ToolkitObjectElement> _toolkitObjects = ToolkitObjectElement.EMPTY_ARRAY; |
| 1253 |
| 1254 /** |
| 1255 * The type defined by the class. |
| 1256 */ |
| 1257 InterfaceType type; |
| 1258 |
| 1259 /** |
| 1260 * An array containing all of the type parameters defined for this class. |
| 1261 */ |
| 1262 List<TypeParameterElement> _typeParameters = TypeParameterElementImpl.EMPTY_AR
RAY; |
| 1263 |
| 1264 /** |
| 1265 * An empty array of class elements. |
| 1266 */ |
| 1267 static List<ClassElement> EMPTY_ARRAY = new List<ClassElement>(0); |
| 1268 |
| 1269 /** |
| 1270 * Initialize a newly created class element to have the given name. |
| 1271 * |
| 1272 * @param name the name of this element |
| 1273 */ |
| 1274 ClassElementImpl.forNode(Identifier name) : super.forNode(name); |
| 1275 |
| 1276 /** |
| 1277 * Initialize a newly created class element to have the given name. |
| 1278 * |
| 1279 * @param name the name of this element |
| 1280 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 1281 * declaration of this element |
| 1282 */ |
| 1283 ClassElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 1284 |
| 1285 @override |
| 1286 accept(ElementVisitor visitor) => visitor.visitClassElement(this); |
| 1287 |
| 1288 /** |
| 1289 * Set the toolkit specific information objects attached to this class. |
| 1290 * |
| 1291 * @param toolkitObjects the toolkit objects attached to this class |
| 1292 */ |
| 1293 void addToolkitObjects(ToolkitObjectElement toolkitObject) { |
| 1294 (toolkitObject as ToolkitObjectElementImpl).enclosingElement = this; |
| 1295 _toolkitObjects = ArrayUtils.add(_toolkitObjects, toolkitObject); |
| 1296 } |
| 1297 |
| 1298 @override |
| 1299 List<PropertyAccessorElement> get accessors => _accessors; |
| 1300 |
| 1301 @override |
| 1302 List<InterfaceType> get allSupertypes { |
| 1303 List<InterfaceType> list = new List<InterfaceType>(); |
| 1304 _collectAllSupertypes(list); |
| 1305 return new List.from(list); |
| 1306 } |
| 1307 |
| 1308 @override |
| 1309 ElementImpl getChild(String identifier) { |
| 1310 // |
| 1311 // The casts in this method are safe because the set methods would have thro
wn a CCE if any of |
| 1312 // the elements in the arrays were not of the expected types. |
| 1313 // |
| 1314 for (PropertyAccessorElement accessor in _accessors) { |
| 1315 if ((accessor as PropertyAccessorElementImpl).identifier == identifier) { |
| 1316 return accessor as PropertyAccessorElementImpl; |
| 1317 } |
| 1318 } |
| 1319 for (ConstructorElement constructor in _constructors) { |
| 1320 if ((constructor as ConstructorElementImpl).identifier == identifier) { |
| 1321 return constructor as ConstructorElementImpl; |
| 1322 } |
| 1323 } |
| 1324 for (FieldElement field in _fields) { |
| 1325 if ((field as FieldElementImpl).identifier == identifier) { |
| 1326 return field as FieldElementImpl; |
| 1327 } |
| 1328 } |
| 1329 for (MethodElement method in _methods) { |
| 1330 if ((method as MethodElementImpl).identifier == identifier) { |
| 1331 return method as MethodElementImpl; |
| 1332 } |
| 1333 } |
| 1334 for (TypeParameterElement typeParameter in _typeParameters) { |
| 1335 if ((typeParameter as TypeParameterElementImpl).identifier == identifier)
{ |
| 1336 return typeParameter as TypeParameterElementImpl; |
| 1337 } |
| 1338 } |
| 1339 return null; |
| 1340 } |
| 1341 |
| 1342 @override |
| 1343 List<ConstructorElement> get constructors => _constructors; |
| 1344 |
| 1345 @override |
| 1346 FieldElement getField(String name) { |
| 1347 for (FieldElement fieldElement in _fields) { |
| 1348 if (name == fieldElement.name) { |
| 1349 return fieldElement; |
| 1350 } |
| 1351 } |
| 1352 return null; |
| 1353 } |
| 1354 |
| 1355 @override |
| 1356 List<FieldElement> get fields => _fields; |
| 1357 |
| 1358 @override |
| 1359 PropertyAccessorElement getGetter(String getterName) { |
| 1360 for (PropertyAccessorElement accessor in _accessors) { |
| 1361 if (accessor.isGetter && accessor.name == getterName) { |
| 1362 return accessor; |
| 1363 } |
| 1364 } |
| 1365 return null; |
| 1366 } |
| 1367 |
| 1368 @override |
| 1369 ElementKind get kind => ElementKind.CLASS; |
| 1370 |
| 1371 @override |
| 1372 MethodElement getMethod(String methodName) { |
| 1373 for (MethodElement method in _methods) { |
| 1374 if (method.name == methodName) { |
| 1375 return method; |
| 1376 } |
| 1377 } |
| 1378 return null; |
| 1379 } |
| 1380 |
| 1381 @override |
| 1382 List<MethodElement> get methods => _methods; |
| 1383 |
| 1384 @override |
| 1385 ConstructorElement getNamedConstructor(String name) { |
| 1386 for (ConstructorElement element in constructors) { |
| 1387 String elementName = element.name; |
| 1388 if (elementName != null && elementName == name) { |
| 1389 return element; |
| 1390 } |
| 1391 } |
| 1392 return null; |
| 1393 } |
| 1394 |
| 1395 @override |
| 1396 ClassDeclaration get node => getNodeMatching((node) => node is ClassDeclaratio
n); |
| 1397 |
| 1398 @override |
| 1399 PropertyAccessorElement getSetter(String setterName) { |
| 1400 // TODO (jwren) revisit- should we append '=' here or require clients to inc
lude it? |
| 1401 // Do we need the check for isSetter below? |
| 1402 if (!StringUtilities.endsWithChar(setterName, 0x3D)) { |
| 1403 setterName += '='; |
| 1404 } |
| 1405 for (PropertyAccessorElement accessor in _accessors) { |
| 1406 if (accessor.isSetter && accessor.name == setterName) { |
| 1407 return accessor; |
| 1408 } |
| 1409 } |
| 1410 return null; |
| 1411 } |
| 1412 |
| 1413 @override |
| 1414 List<ToolkitObjectElement> get toolkitObjects => _toolkitObjects; |
| 1415 |
| 1416 @override |
| 1417 List<TypeParameterElement> get typeParameters => _typeParameters; |
| 1418 |
| 1419 @override |
| 1420 ConstructorElement get unnamedConstructor { |
| 1421 for (ConstructorElement element in constructors) { |
| 1422 String name = element.displayName; |
| 1423 if (name == null || name.isEmpty) { |
| 1424 return element; |
| 1425 } |
| 1426 } |
| 1427 return null; |
| 1428 } |
| 1429 |
| 1430 @override |
| 1431 bool get hasNonFinalField { |
| 1432 List<ClassElement> classesToVisit = new List<ClassElement>(); |
| 1433 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 1434 classesToVisit.add(this); |
| 1435 while (!classesToVisit.isEmpty) { |
| 1436 ClassElement currentElement = classesToVisit.removeAt(0); |
| 1437 if (visitedClasses.add(currentElement)) { |
| 1438 // check fields |
| 1439 for (FieldElement field in currentElement.fields) { |
| 1440 if (!field.isFinal && !field.isConst && !field.isStatic && !field.isSy
nthetic) { |
| 1441 return true; |
| 1442 } |
| 1443 } |
| 1444 // check mixins |
| 1445 for (InterfaceType mixinType in currentElement.mixins) { |
| 1446 ClassElement mixinElement = mixinType.element; |
| 1447 classesToVisit.add(mixinElement); |
| 1448 } |
| 1449 // check super |
| 1450 InterfaceType supertype = currentElement.supertype; |
| 1451 if (supertype != null) { |
| 1452 ClassElement superElement = supertype.element; |
| 1453 if (superElement != null) { |
| 1454 classesToVisit.add(superElement); |
| 1455 } |
| 1456 } |
| 1457 } |
| 1458 } |
| 1459 // not found |
| 1460 return false; |
| 1461 } |
| 1462 |
| 1463 @override |
| 1464 bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER); |
| 1465 |
| 1466 @override |
| 1467 bool get hasStaticMember { |
| 1468 for (MethodElement method in _methods) { |
| 1469 if (method.isStatic) { |
| 1470 return true; |
| 1471 } |
| 1472 } |
| 1473 for (PropertyAccessorElement accessor in _accessors) { |
| 1474 if (accessor.isStatic) { |
| 1475 return true; |
| 1476 } |
| 1477 } |
| 1478 return false; |
| 1479 } |
| 1480 |
| 1481 @override |
| 1482 bool get isAbstract => hasModifier(Modifier.ABSTRACT); |
| 1483 |
| 1484 @override |
| 1485 bool get isEnum => hasModifier(Modifier.ENUM); |
| 1486 |
| 1487 @override |
| 1488 bool get isOrInheritsProxy => _safeIsOrInheritsProxy(this, new HashSet<ClassEl
ement>()); |
| 1489 |
| 1490 @override |
| 1491 bool get isProxy { |
| 1492 for (ElementAnnotation annotation in metadata) { |
| 1493 if (annotation.isProxy) { |
| 1494 return true; |
| 1495 } |
| 1496 } |
| 1497 return false; |
| 1498 } |
| 1499 |
| 1500 @override |
| 1501 bool get isTypedef => hasModifier(Modifier.TYPEDEF); |
| 1502 |
| 1503 @override |
| 1504 bool get isValidMixin => hasModifier(Modifier.MIXIN); |
| 1505 |
| 1506 @override |
| 1507 MethodElement lookUpConcreteMethod(String methodName, LibraryElement library)
=> _internalLookUpConcreteMethod(methodName, library, true); |
| 1508 |
| 1509 @override |
| 1510 PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library
) => _internalLookUpGetter(getterName, library, true); |
| 1511 |
| 1512 @override |
| 1513 PropertyAccessorElement lookUpInheritedConcreteGetter(String getterName, Libra
ryElement library) => _internalLookUpConcreteGetter(getterName, library, false); |
| 1514 |
| 1515 @override |
| 1516 MethodElement lookUpInheritedConcreteMethod(String methodName, LibraryElement
library) => _internalLookUpConcreteMethod(methodName, library, false); |
| 1517 |
| 1518 @override |
| 1519 PropertyAccessorElement lookUpInheritedConcreteSetter(String setterName, Libra
ryElement library) => _internalLookUpConcreteSetter(setterName, library, false); |
| 1520 |
| 1521 @override |
| 1522 MethodElement lookUpInheritedMethod(String methodName, LibraryElement library)
=> _internalLookUpMethod(methodName, library, false); |
| 1523 |
| 1524 @override |
| 1525 MethodElement lookUpMethod(String methodName, LibraryElement library) => _inte
rnalLookUpMethod(methodName, library, true); |
| 1526 |
| 1527 @override |
| 1528 PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library
) => _internalLookUpSetter(setterName, library, true); |
| 1529 |
| 1530 /** |
| 1531 * Set whether this class is abstract to correspond to the given value. |
| 1532 * |
| 1533 * @param isAbstract `true` if the class is abstract |
| 1534 */ |
| 1535 void set abstract(bool isAbstract) { |
| 1536 setModifier(Modifier.ABSTRACT, isAbstract); |
| 1537 } |
| 1538 |
| 1539 /** |
| 1540 * Set the accessors contained in this class to the given accessors. |
| 1541 * |
| 1542 * @param accessors the accessors contained in this class |
| 1543 */ |
| 1544 void set accessors(List<PropertyAccessorElement> accessors) { |
| 1545 for (PropertyAccessorElement accessor in accessors) { |
| 1546 (accessor as PropertyAccessorElementImpl).enclosingElement = this; |
| 1547 } |
| 1548 this._accessors = accessors; |
| 1549 } |
| 1550 |
| 1551 /** |
| 1552 * Set the constructors contained in this class to the given constructors. |
| 1553 * |
| 1554 * @param constructors the constructors contained in this class |
| 1555 */ |
| 1556 void set constructors(List<ConstructorElement> constructors) { |
| 1557 for (ConstructorElement constructor in constructors) { |
| 1558 (constructor as ConstructorElementImpl).enclosingElement = this; |
| 1559 } |
| 1560 this._constructors = constructors; |
| 1561 } |
| 1562 |
| 1563 /** |
| 1564 * Set whether this class is defined by an enum declaration to correspond to t
he given value. |
| 1565 * |
| 1566 * @param isEnum `true` if the class is defined by an enum declaration |
| 1567 */ |
| 1568 void set enum2(bool isEnum) { |
| 1569 setModifier(Modifier.ENUM, isEnum); |
| 1570 } |
| 1571 |
| 1572 /** |
| 1573 * Set the fields contained in this class to the given fields. |
| 1574 * |
| 1575 * @param fields the fields contained in this class |
| 1576 */ |
| 1577 void set fields(List<FieldElement> fields) { |
| 1578 for (FieldElement field in fields) { |
| 1579 (field as FieldElementImpl).enclosingElement = this; |
| 1580 } |
| 1581 this._fields = fields; |
| 1582 } |
| 1583 |
| 1584 /** |
| 1585 * Set whether this class references 'super' to the given value. |
| 1586 * |
| 1587 * @param isReferencedSuper `true` references 'super' |
| 1588 */ |
| 1589 void set hasReferenceToSuper(bool isReferencedSuper) { |
| 1590 setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper); |
| 1591 } |
| 1592 |
| 1593 /** |
| 1594 * Set the methods contained in this class to the given methods. |
| 1595 * |
| 1596 * @param methods the methods contained in this class |
| 1597 */ |
| 1598 void set methods(List<MethodElement> methods) { |
| 1599 for (MethodElement method in methods) { |
| 1600 (method as MethodElementImpl).enclosingElement = this; |
| 1601 } |
| 1602 this._methods = methods; |
| 1603 } |
| 1604 |
| 1605 /** |
| 1606 * Set whether this class is defined by a typedef construct to correspond to t
he given value. |
| 1607 * |
| 1608 * @param isTypedef `true` if the class is defined by a typedef construct |
| 1609 */ |
| 1610 void set typedef(bool isTypedef) { |
| 1611 setModifier(Modifier.TYPEDEF, isTypedef); |
| 1612 } |
| 1613 |
| 1614 /** |
| 1615 * Set the type parameters defined for this class to the given type parameters
. |
| 1616 * |
| 1617 * @param typeParameters the type parameters defined for this class |
| 1618 */ |
| 1619 void set typeParameters(List<TypeParameterElement> typeParameters) { |
| 1620 for (TypeParameterElement typeParameter in typeParameters) { |
| 1621 (typeParameter as TypeParameterElementImpl).enclosingElement = this; |
| 1622 } |
| 1623 this._typeParameters = typeParameters; |
| 1624 } |
| 1625 |
| 1626 /** |
| 1627 * Set whether this class is a valid mixin to correspond to the given value. |
| 1628 * |
| 1629 * @param isValidMixin `true` if this class can be used as a mixin |
| 1630 */ |
| 1631 void set validMixin(bool isValidMixin) { |
| 1632 setModifier(Modifier.MIXIN, isValidMixin); |
| 1633 } |
| 1634 |
| 1635 @override |
| 1636 void visitChildren(ElementVisitor visitor) { |
| 1637 super.visitChildren(visitor); |
| 1638 safelyVisitChildren(_accessors, visitor); |
| 1639 safelyVisitChildren(_constructors, visitor); |
| 1640 safelyVisitChildren(_fields, visitor); |
| 1641 safelyVisitChildren(_methods, visitor); |
| 1642 safelyVisitChildren(_toolkitObjects, visitor); |
| 1643 safelyVisitChildren(_typeParameters, visitor); |
| 1644 } |
| 1645 |
| 1646 @override |
| 1647 void appendTo(JavaStringBuilder builder) { |
| 1648 String name = displayName; |
| 1649 if (name == null) { |
| 1650 builder.append("{unnamed class}"); |
| 1651 } else { |
| 1652 builder.append(name); |
| 1653 } |
| 1654 int variableCount = _typeParameters.length; |
| 1655 if (variableCount > 0) { |
| 1656 builder.append("<"); |
| 1657 for (int i = 0; i < variableCount; i++) { |
| 1658 if (i > 0) { |
| 1659 builder.append(", "); |
| 1660 } |
| 1661 (_typeParameters[i] as TypeParameterElementImpl).appendTo(builder); |
| 1662 } |
| 1663 builder.append(">"); |
| 1664 } |
| 1665 } |
| 1666 |
| 1667 void _collectAllSupertypes(List<InterfaceType> supertypes) { |
| 1668 List<InterfaceType> typesToVisit = new List<InterfaceType>(); |
| 1669 List<ClassElement> visitedClasses = new List<ClassElement>(); |
| 1670 typesToVisit.add(this.type); |
| 1671 while (!typesToVisit.isEmpty) { |
| 1672 InterfaceType currentType = typesToVisit.removeAt(0); |
| 1673 ClassElement currentElement = currentType.element; |
| 1674 if (!visitedClasses.contains(currentElement)) { |
| 1675 visitedClasses.add(currentElement); |
| 1676 if (!identical(currentType, this.type)) { |
| 1677 supertypes.add(currentType); |
| 1678 } |
| 1679 InterfaceType supertype = currentType.superclass; |
| 1680 if (supertype != null) { |
| 1681 typesToVisit.add(supertype); |
| 1682 } |
| 1683 for (InterfaceType type in currentElement.interfaces) { |
| 1684 typesToVisit.add(type); |
| 1685 } |
| 1686 for (InterfaceType type in currentElement.mixins) { |
| 1687 ClassElement element = type.element; |
| 1688 if (!visitedClasses.contains(element)) { |
| 1689 supertypes.add(type); |
| 1690 } |
| 1691 } |
| 1692 } |
| 1693 } |
| 1694 } |
| 1695 |
| 1696 PropertyAccessorElement _internalLookUpConcreteGetter(String getterName, Libra
ryElement library, bool includeThisClass) { |
| 1697 PropertyAccessorElement getter = _internalLookUpGetter(getterName, library,
includeThisClass); |
| 1698 while (getter != null && getter.isAbstract) { |
| 1699 Element definingClass = getter.enclosingElement; |
| 1700 if (definingClass is! ClassElementImpl) { |
| 1701 return null; |
| 1702 } |
| 1703 getter = (definingClass as ClassElementImpl)._internalLookUpGetter(getterN
ame, library, false); |
| 1704 } |
| 1705 return getter; |
| 1706 } |
| 1707 |
| 1708 MethodElement _internalLookUpConcreteMethod(String methodName, LibraryElement
library, bool includeThisClass) { |
| 1709 MethodElement method = _internalLookUpMethod(methodName, library, includeThi
sClass); |
| 1710 while (method != null && method.isAbstract) { |
| 1711 ClassElement definingClass = method.enclosingElement; |
| 1712 if (definingClass == null) { |
| 1713 return null; |
| 1714 } |
| 1715 method = definingClass.lookUpInheritedMethod(methodName, library); |
| 1716 } |
| 1717 return method; |
| 1718 } |
| 1719 |
| 1720 PropertyAccessorElement _internalLookUpConcreteSetter(String setterName, Libra
ryElement library, bool includeThisClass) { |
| 1721 PropertyAccessorElement setter = _internalLookUpSetter(setterName, library,
includeThisClass); |
| 1722 while (setter != null && setter.isAbstract) { |
| 1723 Element definingClass = setter.enclosingElement; |
| 1724 if (definingClass is! ClassElementImpl) { |
| 1725 return null; |
| 1726 } |
| 1727 setter = (definingClass as ClassElementImpl)._internalLookUpSetter(setterN
ame, library, false); |
| 1728 } |
| 1729 return setter; |
| 1730 } |
| 1731 |
| 1732 PropertyAccessorElement _internalLookUpGetter(String getterName, LibraryElemen
t library, bool includeThisClass) { |
| 1733 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 1734 ClassElement currentElement = this; |
| 1735 if (includeThisClass) { |
| 1736 PropertyAccessorElement element = currentElement.getGetter(getterName); |
| 1737 if (element != null && element.isAccessibleIn(library)) { |
| 1738 return element; |
| 1739 } |
| 1740 } |
| 1741 while (currentElement != null && visitedClasses.add(currentElement)) { |
| 1742 for (InterfaceType mixin in currentElement.mixins) { |
| 1743 ClassElement mixinElement = mixin.element; |
| 1744 if (mixinElement != null) { |
| 1745 PropertyAccessorElement element = mixinElement.getGetter(getterName); |
| 1746 if (element != null && element.isAccessibleIn(library)) { |
| 1747 return element; |
| 1748 } |
| 1749 } |
| 1750 } |
| 1751 InterfaceType supertype = currentElement.supertype; |
| 1752 if (supertype == null) { |
| 1753 return null; |
| 1754 } |
| 1755 currentElement = supertype.element; |
| 1756 PropertyAccessorElement element = currentElement.getGetter(getterName); |
| 1757 if (element != null && element.isAccessibleIn(library)) { |
| 1758 return element; |
| 1759 } |
| 1760 } |
| 1761 return null; |
| 1762 } |
| 1763 |
| 1764 MethodElement _internalLookUpMethod(String methodName, LibraryElement library,
bool includeThisClass) { |
| 1765 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 1766 ClassElement currentElement = this; |
| 1767 if (includeThisClass) { |
| 1768 MethodElement element = currentElement.getMethod(methodName); |
| 1769 if (element != null && element.isAccessibleIn(library)) { |
| 1770 return element; |
| 1771 } |
| 1772 } |
| 1773 while (currentElement != null && visitedClasses.add(currentElement)) { |
| 1774 for (InterfaceType mixin in currentElement.mixins) { |
| 1775 ClassElement mixinElement = mixin.element; |
| 1776 if (mixinElement != null) { |
| 1777 MethodElement element = mixinElement.getMethod(methodName); |
| 1778 if (element != null && element.isAccessibleIn(library)) { |
| 1779 return element; |
| 1780 } |
| 1781 } |
| 1782 } |
| 1783 InterfaceType supertype = currentElement.supertype; |
| 1784 if (supertype == null) { |
| 1785 return null; |
| 1786 } |
| 1787 currentElement = supertype.element; |
| 1788 MethodElement element = currentElement.getMethod(methodName); |
| 1789 if (element != null && element.isAccessibleIn(library)) { |
| 1790 return element; |
| 1791 } |
| 1792 } |
| 1793 return null; |
| 1794 } |
| 1795 |
| 1796 PropertyAccessorElement _internalLookUpSetter(String setterName, LibraryElemen
t library, bool includeThisClass) { |
| 1797 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 1798 ClassElement currentElement = this; |
| 1799 if (includeThisClass) { |
| 1800 PropertyAccessorElement element = currentElement.getSetter(setterName); |
| 1801 if (element != null && element.isAccessibleIn(library)) { |
| 1802 return element; |
| 1803 } |
| 1804 } |
| 1805 while (currentElement != null && visitedClasses.add(currentElement)) { |
| 1806 for (InterfaceType mixin in currentElement.mixins) { |
| 1807 ClassElement mixinElement = mixin.element; |
| 1808 if (mixinElement != null) { |
| 1809 PropertyAccessorElement element = mixinElement.getSetter(setterName); |
| 1810 if (element != null && element.isAccessibleIn(library)) { |
| 1811 return element; |
| 1812 } |
| 1813 } |
| 1814 } |
| 1815 InterfaceType supertype = currentElement.supertype; |
| 1816 if (supertype == null) { |
| 1817 return null; |
| 1818 } |
| 1819 currentElement = supertype.element; |
| 1820 PropertyAccessorElement element = currentElement.getSetter(setterName); |
| 1821 if (element != null && element.isAccessibleIn(library)) { |
| 1822 return element; |
| 1823 } |
| 1824 } |
| 1825 return null; |
| 1826 } |
| 1827 |
| 1828 bool _safeIsOrInheritsProxy(ClassElement classElt, HashSet<ClassElement> visit
edClassElts) { |
| 1829 if (visitedClassElts.contains(classElt)) { |
| 1830 return false; |
| 1831 } |
| 1832 visitedClassElts.add(classElt); |
| 1833 if (classElt.isProxy) { |
| 1834 return true; |
| 1835 } else if (classElt.supertype != null && _safeIsOrInheritsProxy(classElt.sup
ertype.element, visitedClassElts)) { |
| 1836 return true; |
| 1837 } |
| 1838 List<InterfaceType> supertypes = classElt.interfaces; |
| 1839 for (int i = 0; i < supertypes.length; i++) { |
| 1840 if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { |
| 1841 return true; |
| 1842 } |
| 1843 } |
| 1844 supertypes = classElt.mixins; |
| 1845 for (int i = 0; i < supertypes.length; i++) { |
| 1846 if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { |
| 1847 return true; |
| 1848 } |
| 1849 } |
| 1850 return false; |
| 1851 } |
| 1852 } |
| 1853 |
| 1854 /** |
| 1855 * The interface `ClassMemberElement` defines the behavior of elements that are
contained |
| 1856 * within a [ClassElement]. |
| 1857 */ |
| 1858 abstract class ClassMemberElement implements Element { |
| 1859 /** |
| 1860 * Return the type in which this member is defined. |
| 1861 * |
| 1862 * @return the type in which this member is defined |
| 1863 */ |
| 1864 @override |
| 1865 ClassElement get enclosingElement; |
| 1866 |
| 1867 /** |
| 1868 * Return `true` if this element is a static element. A static element is an e
lement that is |
| 1869 * not associated with a particular instance, but rather with an entire librar
y or class. |
| 1870 * |
| 1871 * @return `true` if this executable element is a static element |
| 1872 */ |
| 1873 bool get isStatic; |
| 1874 } |
| 1875 |
| 1876 /** |
| 1877 * The interface `CompilationUnitElement` defines the behavior of elements repre
senting a |
| 1878 * compilation unit. |
| 1879 */ |
| 1880 abstract class CompilationUnitElement implements Element, UriReferencedElement { |
| 1881 /** |
| 1882 * Return an array containing all of the top-level accessors (getters and sett
ers) contained in |
| 1883 * this compilation unit. |
| 1884 * |
| 1885 * @return the top-level accessors contained in this compilation unit |
| 1886 */ |
| 1887 List<PropertyAccessorElement> get accessors; |
| 1888 |
| 1889 /** |
| 1890 * Return an array containing all of the Angular views defined in this compila
tion unit. The array |
| 1891 * will be empty if the element does not have any Angular views or if the comp
ilation unit has not |
| 1892 * yet had toolkit references resolved. |
| 1893 * |
| 1894 * @return the Angular views defined in this compilation unit. |
| 1895 */ |
| 1896 List<AngularViewElement> get angularViews; |
| 1897 |
| 1898 /** |
| 1899 * Return the library in which this compilation unit is defined. |
| 1900 * |
| 1901 * @return the library in which this compilation unit is defined |
| 1902 */ |
| 1903 @override |
| 1904 LibraryElement get enclosingElement; |
| 1905 |
| 1906 /** |
| 1907 * Return the enum defined in this compilation unit that has the given name, o
r `null` if |
| 1908 * this compilation unit does not define an enum with the given name. |
| 1909 * |
| 1910 * @param enumName the name of the enum to be returned |
| 1911 * @return the enum with the given name that is defined in this compilation un
it |
| 1912 */ |
| 1913 ClassElement getEnum(String enumName); |
| 1914 |
| 1915 /** |
| 1916 * Return an array containing all of the enums contained in this compilation u
nit. |
| 1917 * |
| 1918 * @return an array containing all of the enums contained in this compilation
unit |
| 1919 */ |
| 1920 List<ClassElement> get enums; |
| 1921 |
| 1922 /** |
| 1923 * Return an array containing all of the top-level functions contained in this
compilation unit. |
| 1924 * |
| 1925 * @return the top-level functions contained in this compilation unit |
| 1926 */ |
| 1927 List<FunctionElement> get functions; |
| 1928 |
| 1929 /** |
| 1930 * Return an array containing all of the function type aliases contained in th
is compilation unit. |
| 1931 * |
| 1932 * @return the function type aliases contained in this compilation unit |
| 1933 */ |
| 1934 List<FunctionTypeAliasElement> get functionTypeAliases; |
| 1935 |
| 1936 /** |
| 1937 * Return the resolved [CompilationUnit] node that declares this element. |
| 1938 * |
| 1939 * This method is expensive, because resolved AST might be evicted from cache,
so parsing and |
| 1940 * resolving will be performed. |
| 1941 * |
| 1942 * @return the resolved [CompilationUnit], not `null`. |
| 1943 */ |
| 1944 @override |
| 1945 CompilationUnit get node; |
| 1946 |
| 1947 /** |
| 1948 * Return an array containing all of the top-level variables contained in this
compilation unit. |
| 1949 * |
| 1950 * @return the top-level variables contained in this compilation unit |
| 1951 */ |
| 1952 List<TopLevelVariableElement> get topLevelVariables; |
| 1953 |
| 1954 /** |
| 1955 * Return the class defined in this compilation unit that has the given name,
or `null` if |
| 1956 * this compilation unit does not define a class with the given name. |
| 1957 * |
| 1958 * @param className the name of the class to be returned |
| 1959 * @return the class with the given name that is defined in this compilation u
nit |
| 1960 */ |
| 1961 ClassElement getType(String className); |
| 1962 |
| 1963 /** |
| 1964 * Return an array containing all of the classes contained in this compilation
unit. |
| 1965 * |
| 1966 * @return the classes contained in this compilation unit |
| 1967 */ |
| 1968 List<ClassElement> get types; |
| 1969 |
| 1970 /** |
| 1971 * Return `true` if this compilation unit defines a top-level function named |
| 1972 * `loadLibrary`. |
| 1973 * |
| 1974 * @return `true` if this compilation unit defines a top-level function named |
| 1975 * `loadLibrary` |
| 1976 */ |
| 1977 bool get hasLoadLibraryFunction; |
| 1978 } |
| 1979 |
| 1980 /** |
| 1981 * Instances of the class `CompilationUnitElementImpl` implement a |
| 1982 * [CompilationUnitElement]. |
| 1983 */ |
| 1984 class CompilationUnitElementImpl extends UriReferencedElementImpl implements Com
pilationUnitElement { |
| 1985 /** |
| 1986 * An empty array of compilation unit elements. |
| 1987 */ |
| 1988 static List<CompilationUnitElement> EMPTY_ARRAY = new List<CompilationUnitElem
ent>(0); |
| 1989 |
| 1990 /** |
| 1991 * The source that corresponds to this compilation unit. |
| 1992 */ |
| 1993 Source source; |
| 1994 |
| 1995 /** |
| 1996 * An array containing all of the top-level accessors (getters and setters) co
ntained in this |
| 1997 * compilation unit. |
| 1998 */ |
| 1999 List<PropertyAccessorElement> _accessors = PropertyAccessorElementImpl.EMPTY_A
RRAY; |
| 2000 |
| 2001 /** |
| 2002 * An array containing all of the enums contained in this compilation unit. |
| 2003 */ |
| 2004 List<ClassElement> _enums = ClassElementImpl.EMPTY_ARRAY; |
| 2005 |
| 2006 /** |
| 2007 * An array containing all of the top-level functions contained in this compil
ation unit. |
| 2008 */ |
| 2009 List<FunctionElement> _functions = FunctionElementImpl.EMPTY_ARRAY; |
| 2010 |
| 2011 /** |
| 2012 * A table mapping elements to associated toolkit objects. |
| 2013 */ |
| 2014 Map<Element, List<ToolkitObjectElement>> _toolkitObjects = {}; |
| 2015 |
| 2016 /** |
| 2017 * An array containing all of the function type aliases contained in this comp
ilation unit. |
| 2018 */ |
| 2019 List<FunctionTypeAliasElement> _typeAliases = FunctionTypeAliasElementImpl.EMP
TY_ARRAY; |
| 2020 |
| 2021 /** |
| 2022 * An array containing all of the types contained in this compilation unit. |
| 2023 */ |
| 2024 List<ClassElement> _types = ClassElementImpl.EMPTY_ARRAY; |
| 2025 |
| 2026 /** |
| 2027 * An array containing all of the variables contained in this compilation unit
. |
| 2028 */ |
| 2029 List<TopLevelVariableElement> _variables = TopLevelVariableElementImpl.EMPTY_A
RRAY; |
| 2030 |
| 2031 /** |
| 2032 * An array containing all of the Angular views contained in this compilation
unit. |
| 2033 */ |
| 2034 List<AngularViewElement> _angularViews = AngularViewElement.EMPTY_ARRAY; |
| 2035 |
| 2036 /** |
| 2037 * Initialize a newly created compilation unit element to have the given name. |
| 2038 * |
| 2039 * @param name the name of this element |
| 2040 */ |
| 2041 CompilationUnitElementImpl(String name) : super(name, -1); |
| 2042 |
| 2043 @override |
| 2044 accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this); |
| 2045 |
| 2046 @override |
| 2047 bool operator ==(Object object) => object != null && runtimeType == object.run
timeType && source == (object as CompilationUnitElementImpl).source; |
| 2048 |
| 2049 @override |
| 2050 List<PropertyAccessorElement> get accessors => _accessors; |
| 2051 |
| 2052 @override |
| 2053 List<AngularViewElement> get angularViews => _angularViews; |
| 2054 |
| 2055 @override |
| 2056 ElementImpl getChild(String identifier) { |
| 2057 // |
| 2058 // The casts in this method are safe because the set methods would have thro
wn a CCE if any of |
| 2059 // the elements in the arrays were not of the expected types. |
| 2060 // |
| 2061 for (PropertyAccessorElement accessor in _accessors) { |
| 2062 if ((accessor as PropertyAccessorElementImpl).identifier == identifier) { |
| 2063 return accessor as PropertyAccessorElementImpl; |
| 2064 } |
| 2065 } |
| 2066 for (VariableElement variable in _variables) { |
| 2067 if ((variable as VariableElementImpl).identifier == identifier) { |
| 2068 return variable as VariableElementImpl; |
| 2069 } |
| 2070 } |
| 2071 for (ExecutableElement function in _functions) { |
| 2072 if ((function as ExecutableElementImpl).identifier == identifier) { |
| 2073 return function as ExecutableElementImpl; |
| 2074 } |
| 2075 } |
| 2076 for (FunctionTypeAliasElement typeAlias in _typeAliases) { |
| 2077 if ((typeAlias as FunctionTypeAliasElementImpl).identifier == identifier)
{ |
| 2078 return typeAlias as FunctionTypeAliasElementImpl; |
| 2079 } |
| 2080 } |
| 2081 for (ClassElement type in _types) { |
| 2082 if ((type as ClassElementImpl).identifier == identifier) { |
| 2083 return type as ClassElementImpl; |
| 2084 } |
| 2085 } |
| 2086 return null; |
| 2087 } |
| 2088 |
| 2089 @override |
| 2090 LibraryElement get enclosingElement => super.enclosingElement as LibraryElemen
t; |
| 2091 |
| 2092 @override |
| 2093 ClassElement getEnum(String enumName) { |
| 2094 for (ClassElement enumDeclaration in _enums) { |
| 2095 if (enumDeclaration.name == enumName) { |
| 2096 return enumDeclaration; |
| 2097 } |
| 2098 } |
| 2099 return null; |
| 2100 } |
| 2101 |
| 2102 @override |
| 2103 List<ClassElement> get enums => _enums; |
| 2104 |
| 2105 @override |
| 2106 List<FunctionElement> get functions => _functions; |
| 2107 |
| 2108 @override |
| 2109 List<FunctionTypeAliasElement> get functionTypeAliases => _typeAliases; |
| 2110 |
| 2111 @override |
| 2112 ElementKind get kind => ElementKind.COMPILATION_UNIT; |
| 2113 |
| 2114 @override |
| 2115 CompilationUnit get node => unit; |
| 2116 |
| 2117 @override |
| 2118 List<TopLevelVariableElement> get topLevelVariables => _variables; |
| 2119 |
| 2120 @override |
| 2121 ClassElement getType(String className) { |
| 2122 for (ClassElement type in _types) { |
| 2123 if (type.name == className) { |
| 2124 return type; |
| 2125 } |
| 2126 } |
| 2127 return null; |
| 2128 } |
| 2129 |
| 2130 @override |
| 2131 List<ClassElement> get types => _types; |
| 2132 |
| 2133 @override |
| 2134 int get hashCode => source.hashCode; |
| 2135 |
| 2136 @override |
| 2137 bool get hasLoadLibraryFunction { |
| 2138 for (int i = 0; i < _functions.length; i++) { |
| 2139 if (_functions[i].name == FunctionElement.LOAD_LIBRARY_NAME) { |
| 2140 return true; |
| 2141 } |
| 2142 } |
| 2143 return false; |
| 2144 } |
| 2145 |
| 2146 /** |
| 2147 * Set the top-level accessors (getters and setters) contained in this compila
tion unit to the |
| 2148 * given accessors. |
| 2149 * |
| 2150 * @param the top-level accessors (getters and setters) contained in this comp
ilation unit |
| 2151 */ |
| 2152 void set accessors(List<PropertyAccessorElement> accessors) { |
| 2153 for (PropertyAccessorElement accessor in accessors) { |
| 2154 (accessor as PropertyAccessorElementImpl).enclosingElement = this; |
| 2155 } |
| 2156 this._accessors = accessors; |
| 2157 } |
| 2158 |
| 2159 /** |
| 2160 * Set the Angular views defined in this compilation unit. |
| 2161 * |
| 2162 * @param angularViews the Angular views defined in this compilation unit |
| 2163 */ |
| 2164 void set angularViews(List<AngularViewElement> angularViews) { |
| 2165 for (AngularViewElement view in angularViews) { |
| 2166 (view as AngularViewElementImpl).enclosingElement = this; |
| 2167 } |
| 2168 this._angularViews = angularViews; |
| 2169 } |
| 2170 |
| 2171 /** |
| 2172 * Set the enums contained in this compilation unit to the given enums. |
| 2173 * |
| 2174 * @param enums enums contained in this compilation unit |
| 2175 */ |
| 2176 void set enums(List<ClassElement> enums) { |
| 2177 for (ClassElement enumDeclaration in enums) { |
| 2178 (enumDeclaration as ClassElementImpl).enclosingElement = this; |
| 2179 } |
| 2180 this._enums = enums; |
| 2181 } |
| 2182 |
| 2183 /** |
| 2184 * Set the top-level functions contained in this compilation unit to the given
functions. |
| 2185 * |
| 2186 * @param functions the top-level functions contained in this compilation unit |
| 2187 */ |
| 2188 void set functions(List<FunctionElement> functions) { |
| 2189 for (FunctionElement function in functions) { |
| 2190 (function as FunctionElementImpl).enclosingElement = this; |
| 2191 } |
| 2192 this._functions = functions; |
| 2193 } |
| 2194 |
| 2195 /** |
| 2196 * Set the top-level variables contained in this compilation unit to the given
variables. |
| 2197 * |
| 2198 * @param variables the top-level variables contained in this compilation unit |
| 2199 */ |
| 2200 void set topLevelVariables(List<TopLevelVariableElement> variables) { |
| 2201 for (TopLevelVariableElement field in variables) { |
| 2202 (field as TopLevelVariableElementImpl).enclosingElement = this; |
| 2203 } |
| 2204 this._variables = variables; |
| 2205 } |
| 2206 |
| 2207 /** |
| 2208 * Set the function type aliases contained in this compilation unit to the giv
en type aliases. |
| 2209 * |
| 2210 * @param typeAliases the function type aliases contained in this compilation
unit |
| 2211 */ |
| 2212 void set typeAliases(List<FunctionTypeAliasElement> typeAliases) { |
| 2213 for (FunctionTypeAliasElement typeAlias in typeAliases) { |
| 2214 (typeAlias as FunctionTypeAliasElementImpl).enclosingElement = this; |
| 2215 } |
| 2216 this._typeAliases = typeAliases; |
| 2217 } |
| 2218 |
| 2219 /** |
| 2220 * Set the types contained in this compilation unit to the given types. |
| 2221 * |
| 2222 * @param types types contained in this compilation unit |
| 2223 */ |
| 2224 void set types(List<ClassElement> types) { |
| 2225 for (ClassElement type in types) { |
| 2226 (type as ClassElementImpl).enclosingElement = this; |
| 2227 } |
| 2228 this._types = types; |
| 2229 } |
| 2230 |
| 2231 @override |
| 2232 void visitChildren(ElementVisitor visitor) { |
| 2233 super.visitChildren(visitor); |
| 2234 safelyVisitChildren(_accessors, visitor); |
| 2235 safelyVisitChildren(_functions, visitor); |
| 2236 safelyVisitChildren(_typeAliases, visitor); |
| 2237 safelyVisitChildren(_types, visitor); |
| 2238 safelyVisitChildren(_variables, visitor); |
| 2239 safelyVisitChildren(_angularViews, visitor); |
| 2240 } |
| 2241 |
| 2242 @override |
| 2243 void appendTo(JavaStringBuilder builder) { |
| 2244 if (source == null) { |
| 2245 builder.append("{compilation unit}"); |
| 2246 } else { |
| 2247 builder.append(source.fullName); |
| 2248 } |
| 2249 } |
| 2250 |
| 2251 @override |
| 2252 String get identifier => source.encoding; |
| 2253 |
| 2254 /** |
| 2255 * Returns the associated toolkit objects. |
| 2256 * |
| 2257 * @param element the [Element] to get toolkit objects for |
| 2258 * @return the associated toolkit objects, may be empty, but not `null` |
| 2259 */ |
| 2260 List<ToolkitObjectElement> _getToolkitObjects(Element element) { |
| 2261 List<ToolkitObjectElement> objects = _toolkitObjects[element]; |
| 2262 if (objects != null) { |
| 2263 return objects; |
| 2264 } |
| 2265 return ToolkitObjectElement.EMPTY_ARRAY; |
| 2266 } |
| 2267 |
| 2268 /** |
| 2269 * Sets the toolkit objects that are associated with the given [Element]. |
| 2270 * |
| 2271 * @param element the [Element] to associate toolkit objects with |
| 2272 * @param objects the toolkit objects to associate |
| 2273 */ |
| 2274 void _setToolkitObjects(Element element, List<ToolkitObjectElement> objects) { |
| 2275 _toolkitObjects[element] = objects; |
| 2276 } |
| 2277 } |
| 2278 |
| 2279 /** |
| 2280 * Instances of the class `ConstFieldElementImpl` implement a `FieldElement` for
a |
| 2281 * 'const' field that has an initializer. |
| 2282 */ |
| 2283 class ConstFieldElementImpl extends FieldElementImpl { |
| 2284 /** |
| 2285 * The result of evaluating this variable's initializer. |
| 2286 */ |
| 2287 EvaluationResultImpl _result; |
| 2288 |
| 2289 /** |
| 2290 * Initialize a newly created field element to have the given name. |
| 2291 * |
| 2292 * @param name the name of this element |
| 2293 */ |
| 2294 ConstFieldElementImpl.con1(Identifier name) : super.forNode(name); |
| 2295 |
| 2296 /** |
| 2297 * Initialize a newly created synthetic field element to have the given name. |
| 2298 * |
| 2299 * @param name the name of this element |
| 2300 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 2301 * declaration of this element |
| 2302 */ |
| 2303 ConstFieldElementImpl.con2(String name, int offset) : super(name, offset); |
| 2304 |
| 2305 @override |
| 2306 EvaluationResultImpl get evaluationResult => _result; |
| 2307 |
| 2308 @override |
| 2309 void set evaluationResult(EvaluationResultImpl result) { |
| 2310 this._result = result; |
| 2311 } |
| 2312 } |
| 2313 |
| 2314 /** |
| 2315 * Instances of the class `ConstLocalVariableElementImpl` implement a |
| 2316 * `LocalVariableElement` for a local 'const' variable that has an initializer. |
| 2317 */ |
| 2318 class ConstLocalVariableElementImpl extends LocalVariableElementImpl { |
| 2319 /** |
| 2320 * The result of evaluating this variable's initializer. |
| 2321 */ |
| 2322 EvaluationResultImpl _result; |
| 2323 |
| 2324 /** |
| 2325 * Initialize a newly created local variable element to have the given name. |
| 2326 * |
| 2327 * @param name the name of this element |
| 2328 */ |
| 2329 ConstLocalVariableElementImpl(Identifier name) : super.forNode(name); |
| 2330 |
| 2331 @override |
| 2332 EvaluationResultImpl get evaluationResult => _result; |
| 2333 |
| 2334 @override |
| 2335 void set evaluationResult(EvaluationResultImpl result) { |
| 2336 this._result = result; |
| 2337 } |
| 2338 } |
| 2339 |
| 2340 /** |
| 2341 * Instances of the class `ConstTopLevelVariableElementImpl` implement a |
| 2342 * `TopLevelVariableElement` for a top-level 'const' variable that has an initia
lizer. |
| 2343 */ |
| 2344 class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl { |
| 2345 /** |
| 2346 * The result of evaluating this variable's initializer. |
| 2347 */ |
| 2348 EvaluationResultImpl _result; |
| 2349 |
| 2350 /** |
| 2351 * Initialize a newly created top-level variable element to have the given nam
e. |
| 2352 * |
| 2353 * @param name the name of this element |
| 2354 */ |
| 2355 ConstTopLevelVariableElementImpl(Identifier name) : super.forNode(name); |
| 2356 |
| 2357 @override |
| 2358 EvaluationResultImpl get evaluationResult => _result; |
| 2359 |
| 2360 @override |
| 2361 void set evaluationResult(EvaluationResultImpl result) { |
| 2362 this._result = result; |
| 2363 } |
| 2364 } |
| 2365 |
| 2366 /** |
| 2367 * The interface `ConstructorElement` defines the behavior of elements represent
ing a |
| 2368 * constructor or a factory method defined within a type. |
| 2369 */ |
| 2370 abstract class ConstructorElement implements ClassMemberElement, ExecutableEleme
nt { |
| 2371 /** |
| 2372 * Return the resolved [ConstructorDeclaration] node that declares this |
| 2373 * [ConstructorElement] . |
| 2374 * |
| 2375 * This method is expensive, because resolved AST might be evicted from cache,
so parsing and |
| 2376 * resolving will be performed. |
| 2377 * |
| 2378 * @return the resolved [ConstructorDeclaration], not `null`. |
| 2379 */ |
| 2380 @override |
| 2381 ConstructorDeclaration get node; |
| 2382 |
| 2383 /** |
| 2384 * Return the constructor to which this constructor is redirecting, or `null`
if this |
| 2385 * constructor does not redirect to another constructor or if the library cont
aining this |
| 2386 * constructor has not yet been resolved. |
| 2387 * |
| 2388 * @return the constructor to which this constructor is redirecting |
| 2389 */ |
| 2390 ConstructorElement get redirectedConstructor; |
| 2391 |
| 2392 /** |
| 2393 * Return `true` if this constructor is a const constructor. |
| 2394 * |
| 2395 * @return `true` if this constructor is a const constructor |
| 2396 */ |
| 2397 bool get isConst; |
| 2398 |
| 2399 /** |
| 2400 * Return `true` if this constructor can be used as a default constructor - un
named and has |
| 2401 * no required parameters. |
| 2402 * |
| 2403 * @return `true` if this constructor can be used as a default constructor. |
| 2404 */ |
| 2405 bool get isDefaultConstructor; |
| 2406 |
| 2407 /** |
| 2408 * Return `true` if this constructor represents a factory constructor. |
| 2409 * |
| 2410 * @return `true` if this constructor represents a factory constructor |
| 2411 */ |
| 2412 bool get isFactory; |
| 2413 } |
| 2414 |
| 2415 /** |
| 2416 * Instances of the class `ConstructorElementImpl` implement a `ConstructorEleme
nt`. |
| 2417 */ |
| 2418 class ConstructorElementImpl extends ExecutableElementImpl implements Constructo
rElement { |
| 2419 /** |
| 2420 * An empty array of constructor elements. |
| 2421 */ |
| 2422 static List<ConstructorElement> EMPTY_ARRAY = new List<ConstructorElement>(0); |
| 2423 |
| 2424 /** |
| 2425 * The constructor to which this constructor is redirecting. |
| 2426 */ |
| 2427 ConstructorElement redirectedConstructor; |
| 2428 |
| 2429 /** |
| 2430 * The initializers for this constructor (used for evaluating constant instanc
e creation |
| 2431 * expressions). |
| 2432 */ |
| 2433 List<ConstructorInitializer> constantInitializers; |
| 2434 |
| 2435 /** |
| 2436 * Initialize a newly created constructor element to have the given name. |
| 2437 * |
| 2438 * @param name the name of this element |
| 2439 */ |
| 2440 ConstructorElementImpl.forNode(Identifier name) : super.forNode(name); |
| 2441 |
| 2442 /** |
| 2443 * Initialize a newly created constructor element to have the given name. |
| 2444 * |
| 2445 * @param name the name of this element |
| 2446 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 2447 * declaration of this element |
| 2448 */ |
| 2449 ConstructorElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 2450 |
| 2451 @override |
| 2452 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this); |
| 2453 |
| 2454 @override |
| 2455 ClassElement get enclosingElement => super.enclosingElement as ClassElement; |
| 2456 |
| 2457 @override |
| 2458 ElementKind get kind => ElementKind.CONSTRUCTOR; |
| 2459 |
| 2460 @override |
| 2461 ConstructorDeclaration get node => getNodeMatching((node) => node is Construct
orDeclaration); |
| 2462 |
| 2463 @override |
| 2464 bool get isConst => hasModifier(Modifier.CONST); |
| 2465 |
| 2466 @override |
| 2467 bool get isDefaultConstructor { |
| 2468 // unnamed |
| 2469 String name = this.name; |
| 2470 if (name != null && name.length != 0) { |
| 2471 return false; |
| 2472 } |
| 2473 // no required parameters |
| 2474 for (ParameterElement parameter in parameters) { |
| 2475 if (parameter.parameterKind == ParameterKind.REQUIRED) { |
| 2476 return false; |
| 2477 } |
| 2478 } |
| 2479 // OK, can be used as default constructor |
| 2480 return true; |
| 2481 } |
| 2482 |
| 2483 @override |
| 2484 bool get isFactory => hasModifier(Modifier.FACTORY); |
| 2485 |
| 2486 @override |
| 2487 bool get isStatic => false; |
| 2488 |
| 2489 /** |
| 2490 * Set whether this constructor represents a 'const' constructor to the given
value. |
| 2491 * |
| 2492 * @param isConst `true` if this constructor represents a 'const' constructor |
| 2493 */ |
| 2494 void set const2(bool isConst) { |
| 2495 setModifier(Modifier.CONST, isConst); |
| 2496 } |
| 2497 |
| 2498 /** |
| 2499 * Set whether this constructor represents a factory method to the given value
. |
| 2500 * |
| 2501 * @param isFactory `true` if this constructor represents a factory method |
| 2502 */ |
| 2503 void set factory(bool isFactory) { |
| 2504 setModifier(Modifier.FACTORY, isFactory); |
| 2505 } |
| 2506 |
| 2507 @override |
| 2508 void appendTo(JavaStringBuilder builder) { |
| 2509 builder.append(enclosingElement.displayName); |
| 2510 String name = displayName; |
| 2511 if (name != null && !name.isEmpty) { |
| 2512 builder.append("."); |
| 2513 builder.append(name); |
| 2514 } |
| 2515 super.appendTo(builder); |
| 2516 } |
| 2517 } |
| 2518 |
| 2519 /** |
| 2520 * Instances of the class `ConstructorMember` represent a constructor element de
fined in a |
| 2521 * parameterized type where the values of the type parameters are known. |
| 2522 */ |
| 2523 class ConstructorMember extends ExecutableMember implements ConstructorElement { |
| 2524 /** |
| 2525 * If the given constructor's type is different when any type parameters from
the defining type's |
| 2526 * declaration are replaced with the actual type arguments from the defining t
ype, create a |
| 2527 * constructor member representing the given constructor. Return the member th
at was created, or |
| 2528 * the base constructor if no member was created. |
| 2529 * |
| 2530 * @param baseConstructor the base constructor for which a member might be cre
ated |
| 2531 * @param definingType the type defining the parameters and arguments to be us
ed in the |
| 2532 * substitution |
| 2533 * @return the constructor element that will return the correctly substituted
types |
| 2534 */ |
| 2535 static ConstructorElement from(ConstructorElement baseConstructor, InterfaceTy
pe definingType) { |
| 2536 if (baseConstructor == null || definingType.typeArguments.length == 0) { |
| 2537 return baseConstructor; |
| 2538 } |
| 2539 FunctionType baseType = baseConstructor.type; |
| 2540 if (baseType == null) { |
| 2541 // TODO(brianwilkerson) We need to understand when this can happen. |
| 2542 return baseConstructor; |
| 2543 } |
| 2544 List<DartType> argumentTypes = definingType.typeArguments; |
| 2545 List<DartType> parameterTypes = definingType.element.type.typeArguments; |
| 2546 FunctionType substitutedType = baseType.substitute2(argumentTypes, parameter
Types); |
| 2547 if (baseType == substitutedType) { |
| 2548 return baseConstructor; |
| 2549 } |
| 2550 // TODO(brianwilkerson) Consider caching the substituted type in the instanc
e. It would use more |
| 2551 // memory but speed up some operations. We need to see how often the type is
being re-computed. |
| 2552 return new ConstructorMember(baseConstructor, definingType); |
| 2553 } |
| 2554 |
| 2555 /** |
| 2556 * Initialize a newly created element to represent a constructor of the given
parameterized type. |
| 2557 * |
| 2558 * @param baseElement the element on which the parameterized element was creat
ed |
| 2559 * @param definingType the type in which the element is defined |
| 2560 */ |
| 2561 ConstructorMember(ConstructorElement baseElement, InterfaceType definingType)
: super(baseElement, definingType); |
| 2562 |
| 2563 @override |
| 2564 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this); |
| 2565 |
| 2566 @override |
| 2567 ConstructorElement get baseElement => super.baseElement as ConstructorElement; |
| 2568 |
| 2569 @override |
| 2570 ClassElement get enclosingElement => baseElement.enclosingElement; |
| 2571 |
| 2572 @override |
| 2573 ConstructorDeclaration get node => baseElement.node; |
| 2574 |
| 2575 @override |
| 2576 ConstructorElement get redirectedConstructor => from(baseElement.redirectedCon
structor, definingType); |
| 2577 |
| 2578 @override |
| 2579 bool get isConst => baseElement.isConst; |
| 2580 |
| 2581 @override |
| 2582 bool get isDefaultConstructor => baseElement.isDefaultConstructor; |
| 2583 |
| 2584 @override |
| 2585 bool get isFactory => baseElement.isFactory; |
| 2586 |
| 2587 @override |
| 2588 String toString() { |
| 2589 ConstructorElement baseElement = this.baseElement; |
| 2590 List<ParameterElement> parameters = this.parameters; |
| 2591 FunctionType type = this.type; |
| 2592 JavaStringBuilder builder = new JavaStringBuilder(); |
| 2593 builder.append(baseElement.enclosingElement.displayName); |
| 2594 String name = displayName; |
| 2595 if (name != null && !name.isEmpty) { |
| 2596 builder.append("."); |
| 2597 builder.append(name); |
| 2598 } |
| 2599 builder.append("("); |
| 2600 int parameterCount = parameters.length; |
| 2601 for (int i = 0; i < parameterCount; i++) { |
| 2602 if (i > 0) { |
| 2603 builder.append(", "); |
| 2604 } |
| 2605 builder.append(parameters[i]).toString(); |
| 2606 } |
| 2607 builder.append(")"); |
| 2608 if (type != null) { |
| 2609 builder.append(Element.RIGHT_ARROW); |
| 2610 builder.append(type.returnType); |
| 2611 } |
| 2612 return builder.toString(); |
| 2613 } |
| 2614 |
| 2615 @override |
| 2616 InterfaceType get definingType => super.definingType as InterfaceType; |
| 2617 } |
| 2618 |
| 2619 /** |
| 2620 * The interface `Type` defines the behavior of objects representing the declare
d type of |
| 2621 * elements in the element model. |
| 2622 */ |
| 2623 abstract class DartType { |
| 2624 /** |
| 2625 * Return the name of this type as it should appear when presented to users in
contexts such as |
| 2626 * error messages. |
| 2627 * |
| 2628 * @return the name of this type |
| 2629 */ |
| 2630 String get displayName; |
| 2631 |
| 2632 /** |
| 2633 * Return the element representing the declaration of this type, or `null` if
the type has |
| 2634 * not, or cannot, be associated with an element. The former case will occur i
f the element model |
| 2635 * is not yet complete; the latter case will occur if this object represents a
n undefined type. |
| 2636 * |
| 2637 * @return the element representing the declaration of this type |
| 2638 */ |
| 2639 Element get element; |
| 2640 |
| 2641 /** |
| 2642 * Return the least upper bound of this type and the given type, or `null` if
there is no |
| 2643 * least upper bound. |
| 2644 * |
| 2645 * @param type the other type used to compute the least upper bound |
| 2646 * @return the least upper bound of this type and the given type |
| 2647 */ |
| 2648 DartType getLeastUpperBound(DartType type); |
| 2649 |
| 2650 /** |
| 2651 * Return the name of this type, or `null` if the type does not have a name, s
uch as when |
| 2652 * the type represents the type of an unnamed function. |
| 2653 * |
| 2654 * @return the name of this type |
| 2655 */ |
| 2656 String get name; |
| 2657 |
| 2658 /** |
| 2659 * Return `true` if this type is assignable to the given type. A type <i>T</i>
may be |
| 2660 * assigned to a type <i>S</i>, written <i>T</i> ⇔ <i>S</i>, iff either <
i>T</i> <: <i>S</i> |
| 2661 * or <i>S</i> <: <i>T</i>. |
| 2662 * |
| 2663 * @param type the type being compared with this type |
| 2664 * @return `true` if this type is assignable to the given type |
| 2665 */ |
| 2666 bool isAssignableTo(DartType type); |
| 2667 |
| 2668 /** |
| 2669 * Return `true` if this type represents the bottom type. |
| 2670 * |
| 2671 * @return `true` if this type represents the bottom type |
| 2672 */ |
| 2673 bool get isBottom; |
| 2674 |
| 2675 /** |
| 2676 * Return `true` if this type represents the type 'Function' defined in the da
rt:core |
| 2677 * library. |
| 2678 * |
| 2679 * @return `true` if this type represents the type 'Function' defined in the d
art:core |
| 2680 * library |
| 2681 */ |
| 2682 bool get isDartCoreFunction; |
| 2683 |
| 2684 /** |
| 2685 * Return `true` if this type represents the type 'dynamic'. |
| 2686 * |
| 2687 * @return `true` if this type represents the type 'dynamic' |
| 2688 */ |
| 2689 bool get isDynamic; |
| 2690 |
| 2691 /** |
| 2692 * Return `true` if this type is more specific than the given type. |
| 2693 * |
| 2694 * @param type the type being compared with this type |
| 2695 * @return `true` if this type is more specific than the given type |
| 2696 */ |
| 2697 bool isMoreSpecificThan(DartType type); |
| 2698 |
| 2699 /** |
| 2700 * Return `true` if this type represents the type 'Object'. |
| 2701 * |
| 2702 * @return `true` if this type represents the type 'Object' |
| 2703 */ |
| 2704 bool get isObject; |
| 2705 |
| 2706 /** |
| 2707 * Return `true` if this type is a subtype of the given type. |
| 2708 * |
| 2709 * @param type the type being compared with this type |
| 2710 * @return `true` if this type is a subtype of the given type |
| 2711 */ |
| 2712 bool isSubtypeOf(DartType type); |
| 2713 |
| 2714 /** |
| 2715 * Return `true` if this type is a supertype of the given type. A type <i>S</i
> is a |
| 2716 * supertype of <i>T</i>, written <i>S</i> :> <i>T</i>, iff <i>T</i> is a subt
ype of <i>S</i>. |
| 2717 * |
| 2718 * @param type the type being compared with this type |
| 2719 * @return `true` if this type is a supertype of the given type |
| 2720 */ |
| 2721 bool isSupertypeOf(DartType type); |
| 2722 |
| 2723 /** |
| 2724 * Return `true` if this type represents the type 'void'. |
| 2725 * |
| 2726 * @return `true` if this type represents the type 'void' |
| 2727 */ |
| 2728 bool get isVoid; |
| 2729 |
| 2730 /** |
| 2731 * Return the type resulting from substituting the given arguments for the giv
en parameters in |
| 2732 * this type. The specification defines this operation in section 2: <blockquo
te> The notation |
| 2733 * <i>[x<sub>1</sub>, ..., x<sub>n</sub>/y<sub>1</sub>, ..., y<sub>n</sub>]E</
i> denotes a copy of |
| 2734 * <i>E</i> in which all occurrences of <i>y<sub>i</sub>, 1 <= i <= n</i> have
been replaced with |
| 2735 * <i>x<sub>i</sub></i>.</blockquote> Note that, contrary to the specification
, this method will |
| 2736 * not create a copy of this type if no substitutions were required, but will
return this type |
| 2737 * directly. |
| 2738 * |
| 2739 * @param argumentTypes the actual type arguments being substituted for the pa
rameters |
| 2740 * @param parameterTypes the parameters to be replaced |
| 2741 * @return the result of performing the substitution |
| 2742 */ |
| 2743 DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTyp
es); |
| 2744 } |
| 2745 |
| 2746 /** |
| 2747 * Instances of the class `DefaultFieldFormalParameterElementImpl` implement a |
| 2748 * `FieldFormalParameterElementImpl` for parameters that have an initializer. |
| 2749 */ |
| 2750 class DefaultFieldFormalParameterElementImpl extends FieldFormalParameterElement
Impl { |
| 2751 /** |
| 2752 * The result of evaluating this variable's initializer. |
| 2753 */ |
| 2754 EvaluationResultImpl _result; |
| 2755 |
| 2756 /** |
| 2757 * Initialize a newly created parameter element to have the given name. |
| 2758 * |
| 2759 * @param name the name of this element |
| 2760 */ |
| 2761 DefaultFieldFormalParameterElementImpl(Identifier name) : super(name); |
| 2762 |
| 2763 @override |
| 2764 EvaluationResultImpl get evaluationResult => _result; |
| 2765 |
| 2766 @override |
| 2767 void set evaluationResult(EvaluationResultImpl result) { |
| 2768 this._result = result; |
| 2769 } |
| 2770 } |
| 2771 |
| 2772 /** |
| 2773 * Instances of the class `DefaultParameterElementImpl` implement a `ParameterEl
ement` |
| 2774 * for parameters that have an initializer. |
| 2775 */ |
| 2776 class DefaultParameterElementImpl extends ParameterElementImpl { |
| 2777 /** |
| 2778 * The result of evaluating this variable's initializer. |
| 2779 */ |
| 2780 EvaluationResultImpl _result; |
| 2781 |
| 2782 /** |
| 2783 * Initialize a newly created parameter element to have the given name. |
| 2784 * |
| 2785 * @param name the name of this element |
| 2786 */ |
| 2787 DefaultParameterElementImpl(Identifier name) : super.forNode(name); |
| 2788 |
| 2789 @override |
| 2790 EvaluationResultImpl get evaluationResult => _result; |
| 2791 |
| 2792 @override |
| 2793 void set evaluationResult(EvaluationResultImpl result) { |
| 2794 this._result = result; |
| 2795 } |
| 2796 } |
| 2797 |
| 2798 /** |
| 2799 * Instances of the class `DynamicElementImpl` represent the synthetic element r
epresenting |
| 2800 * the declaration of the type `dynamic`. |
| 2801 */ |
| 2802 class DynamicElementImpl extends ElementImpl { |
| 2803 /** |
| 2804 * Return the unique instance of this class. |
| 2805 * |
| 2806 * @return the unique instance of this class |
| 2807 */ |
| 2808 static DynamicElementImpl get instance => DynamicTypeImpl.instance.element as
DynamicElementImpl; |
| 2809 |
| 2810 /** |
| 2811 * The type defined by this element. |
| 2812 */ |
| 2813 DynamicTypeImpl type; |
| 2814 |
| 2815 /** |
| 2816 * Initialize a newly created instance of this class. Instances of this class
should <b>not</b> be |
| 2817 * created except as part of creating the type associated with this element. T
he single instance |
| 2818 * of this class should be accessed through the method [getInstance]. |
| 2819 */ |
| 2820 DynamicElementImpl() : super(Keyword.DYNAMIC.syntax, -1) { |
| 2821 setModifier(Modifier.SYNTHETIC, true); |
| 2822 } |
| 2823 |
| 2824 @override |
| 2825 accept(ElementVisitor visitor) => null; |
| 2826 |
| 2827 @override |
| 2828 ElementKind get kind => ElementKind.DYNAMIC; |
| 2829 } |
| 2830 |
| 2831 /** |
| 2832 * The unique instance of the class `DynamicTypeImpl` implements the type `dynam
ic`. |
| 2833 */ |
| 2834 class DynamicTypeImpl extends TypeImpl { |
| 2835 /** |
| 2836 * The unique instance of this class. |
| 2837 */ |
| 2838 static DynamicTypeImpl _INSTANCE = new DynamicTypeImpl(); |
| 2839 |
| 2840 /** |
| 2841 * Return the unique instance of this class. |
| 2842 * |
| 2843 * @return the unique instance of this class |
| 2844 */ |
| 2845 static DynamicTypeImpl get instance => _INSTANCE; |
| 2846 |
| 2847 /** |
| 2848 * Prevent the creation of instances of this class. |
| 2849 */ |
| 2850 DynamicTypeImpl() : super(new DynamicElementImpl(), Keyword.DYNAMIC.syntax) { |
| 2851 (element as DynamicElementImpl).type = this; |
| 2852 } |
| 2853 |
| 2854 @override |
| 2855 bool operator ==(Object object) => identical(object, this); |
| 2856 |
| 2857 @override |
| 2858 int get hashCode => 1; |
| 2859 |
| 2860 @override |
| 2861 bool get isDynamic => true; |
| 2862 |
| 2863 @override |
| 2864 bool isSupertypeOf(DartType type) => true; |
| 2865 |
| 2866 @override |
| 2867 DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTyp
es) { |
| 2868 int length = parameterTypes.length; |
| 2869 for (int i = 0; i < length; i++) { |
| 2870 if (parameterTypes[i] == this) { |
| 2871 return argumentTypes[i]; |
| 2872 } |
| 2873 } |
| 2874 return this; |
| 2875 } |
| 2876 |
| 2877 @override |
| 2878 bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => id
entical(object, this); |
| 2879 |
| 2880 @override |
| 2881 bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_
TypePair> visitedTypePairs) { |
| 2882 // T is S |
| 2883 if (identical(this, type)) { |
| 2884 return true; |
| 2885 } |
| 2886 // else |
| 2887 return withDynamic; |
| 2888 } |
| 2889 |
| 2890 @override |
| 2891 bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePair
s) => true; |
| 2892 } |
| 2893 |
| 2894 /** |
| 2895 * The interface `Element` defines the behavior common to all of the elements in
the element |
| 2896 * model. Generally speaking, the element model is a semantic model of the progr
am that represents |
| 2897 * things that are declared with a name and hence can be referenced elsewhere in
the code. |
| 2898 * |
| 2899 * There are two exceptions to the general case. First, there are elements in th
e element model that |
| 2900 * are created for the convenience of various kinds of analysis but that do not
have any |
| 2901 * corresponding declaration within the source code. Such elements are marked as
being |
| 2902 * <i>synthetic</i>. Examples of synthetic elements include |
| 2903 * * default constructors in classes that do not define any explicit constructor
s, |
| 2904 * * getters and setters that are induced by explicit field declarations, |
| 2905 * * fields that are induced by explicit declarations of getters and setters, an
d |
| 2906 * * functions representing the initialization expression for a variable. |
| 2907 * |
| 2908 * Second, there are elements in the element model that do not have a name. Thes
e correspond to |
| 2909 * unnamed functions and exist in order to more accurately represent the semanti
c structure of the |
| 2910 * program. |
| 2911 */ |
| 2912 abstract class Element { |
| 2913 /** |
| 2914 * An Unicode right arrow. |
| 2915 */ |
| 2916 static final String RIGHT_ARROW = " \u2192 "; |
| 2917 |
| 2918 /** |
| 2919 * A comparator that can be used to sort elements by their name offset. Elemen
ts with a smaller |
| 2920 * offset will be sorted to be before elements with a larger name offset. |
| 2921 */ |
| 2922 static final Comparator<Element> SORT_BY_OFFSET = (Element firstElement, Eleme
nt secondElement) => firstElement.nameOffset - secondElement.nameOffset; |
| 2923 |
| 2924 /** |
| 2925 * Use the given visitor to visit this element. |
| 2926 * |
| 2927 * @param visitor the visitor that will visit this element |
| 2928 * @return the value returned by the visitor as a result of visiting this elem
ent |
| 2929 */ |
| 2930 accept(ElementVisitor visitor); |
| 2931 |
| 2932 /** |
| 2933 * Return the documentation comment for this element as it appears in the orig
inal source |
| 2934 * (complete with the beginning and ending delimiters), or `null` if this elem
ent does not |
| 2935 * have a documentation comment associated with it. This can be a long-running
operation if the |
| 2936 * information needed to access the comment is not cached. |
| 2937 * |
| 2938 * @return this element's documentation comment |
| 2939 * @throws AnalysisException if the documentation comment could not be determi
ned because the |
| 2940 * analysis could not be performed |
| 2941 */ |
| 2942 String computeDocumentationComment(); |
| 2943 |
| 2944 /** |
| 2945 * Return the element of the given class that most immediately encloses this e
lement, or |
| 2946 * `null` if there is no enclosing element of the given class. |
| 2947 * |
| 2948 * @param elementClass the class of the element to be returned |
| 2949 * @return the element that encloses this element |
| 2950 */ |
| 2951 Element getAncestor(Predicate<Element> predicate); |
| 2952 |
| 2953 /** |
| 2954 * Return the analysis context in which this element is defined. |
| 2955 * |
| 2956 * @return the analysis context in which this element is defined |
| 2957 */ |
| 2958 AnalysisContext get context; |
| 2959 |
| 2960 /** |
| 2961 * Return the display name of this element, or `null` if this element does not
have a name. |
| 2962 * |
| 2963 * In most cases the name and the display name are the same. Differences thoug
h are cases such as |
| 2964 * setters where the name of some setter `set f(x)` is `f=`, instead of `f`. |
| 2965 * |
| 2966 * @return the display name of this element |
| 2967 */ |
| 2968 String get displayName; |
| 2969 |
| 2970 /** |
| 2971 * Return the element that either physically or logically encloses this elemen
t. This will be |
| 2972 * `null` if this element is a library because libraries are the top-level ele
ments in the |
| 2973 * model. |
| 2974 * |
| 2975 * @return the element that encloses this element |
| 2976 */ |
| 2977 Element get enclosingElement; |
| 2978 |
| 2979 /** |
| 2980 * Return a display name for the given element that includes the path to the c
ompilation unit in |
| 2981 * which the type is defined. |
| 2982 * |
| 2983 * @param shortName the short display name. If null, [getDisplayName] is used. |
| 2984 * @return a display name that can help distinguish between two types with the
same name |
| 2985 */ |
| 2986 String getExtendedDisplayName(String shortName); |
| 2987 |
| 2988 /** |
| 2989 * Return the kind of element that this is. |
| 2990 * |
| 2991 * @return the kind of this element |
| 2992 */ |
| 2993 ElementKind get kind; |
| 2994 |
| 2995 /** |
| 2996 * Return the library that contains this element. This will be the element its
elf if it is a |
| 2997 * library element. This will be `null` if this element is an HTML file becaus
e HTML files |
| 2998 * are not contained in libraries. |
| 2999 * |
| 3000 * @return the library that contains this element |
| 3001 */ |
| 3002 LibraryElement get library; |
| 3003 |
| 3004 /** |
| 3005 * Return an object representing the location of this element in the element m
odel. The object can |
| 3006 * be used to locate this element at a later time. |
| 3007 * |
| 3008 * @return the location of this element in the element model |
| 3009 */ |
| 3010 ElementLocation get location; |
| 3011 |
| 3012 /** |
| 3013 * Return an array containing all of the metadata associated with this element
. The array will be |
| 3014 * empty if the element does not have any metadata or if the library containin
g this element has |
| 3015 * not yet been resolved. |
| 3016 * |
| 3017 * @return the metadata associated with this element |
| 3018 */ |
| 3019 List<ElementAnnotation> get metadata; |
| 3020 |
| 3021 /** |
| 3022 * Return the name of this element, or `null` if this element does not have a
name. |
| 3023 * |
| 3024 * @return the name of this element |
| 3025 */ |
| 3026 String get name; |
| 3027 |
| 3028 /** |
| 3029 * Return the offset of the name of this element in the file that contains the
declaration of this |
| 3030 * element, or `-1` if this element is synthetic, does not have a name, or oth
erwise does |
| 3031 * not have an offset. |
| 3032 * |
| 3033 * @return the offset of the name of this element |
| 3034 */ |
| 3035 int get nameOffset; |
| 3036 |
| 3037 /** |
| 3038 * Return the resolved [AstNode] node that declares this [Element]. |
| 3039 * |
| 3040 * This method is expensive, because resolved AST might be evicted from cache,
so parsing and |
| 3041 * resolving will be performed. |
| 3042 * |
| 3043 * <b>Note:</b> This method cannot be used in an async environment. |
| 3044 * |
| 3045 * @return the resolved [AstNode], maybe `null` if [Element] is synthetic or |
| 3046 * isn't contained in a compilation unit, such as a [LibraryElement]. |
| 3047 */ |
| 3048 AstNode get node; |
| 3049 |
| 3050 /** |
| 3051 * Return the source that contains this element, or `null` if this element is
not contained |
| 3052 * in a source. |
| 3053 * |
| 3054 * @return the source that contains this element |
| 3055 */ |
| 3056 Source get source; |
| 3057 |
| 3058 /** |
| 3059 * Return the resolved [CompilationUnit] that declares this [Element]. |
| 3060 * |
| 3061 * This method is expensive, because resolved AST might have been already evic
ted from cache, so |
| 3062 * parsing and resolving will be performed. |
| 3063 * |
| 3064 * @return the resolved [CompilationUnit], maybe `null` if synthetic [Element]
. |
| 3065 */ |
| 3066 CompilationUnit get unit; |
| 3067 |
| 3068 /** |
| 3069 * Return `true` if this element, assuming that it is within scope, is accessi
ble to code in |
| 3070 * the given library. This is defined by the Dart Language Specification in se
ction 3.2: |
| 3071 * <blockquote> A declaration <i>m</i> is accessible to library <i>L</i> if <i
>m</i> is declared |
| 3072 * in <i>L</i> or if <i>m</i> is public. </blockquote> |
| 3073 * |
| 3074 * @param library the library in which a possible reference to this element wo
uld occur |
| 3075 * @return `true` if this element is accessible to code in the given library |
| 3076 */ |
| 3077 bool isAccessibleIn(LibraryElement library); |
| 3078 |
| 3079 /** |
| 3080 * Return `true` if this element has an annotation of the form '@deprecated' o
r |
| 3081 * '@Deprecated('..')'. |
| 3082 * |
| 3083 * @return `true` if this element is deprecated |
| 3084 */ |
| 3085 bool get isDeprecated; |
| 3086 |
| 3087 /** |
| 3088 * Return `true` if this element has an annotation of the form '@override'. |
| 3089 * |
| 3090 * @return `true` if this element is overridden |
| 3091 */ |
| 3092 bool get isOverride; |
| 3093 |
| 3094 /** |
| 3095 * Return `true` if this element is private. Private elements are visible only
within the |
| 3096 * library in which they are declared. |
| 3097 * |
| 3098 * @return `true` if this element is private |
| 3099 */ |
| 3100 bool get isPrivate; |
| 3101 |
| 3102 /** |
| 3103 * Return `true` if this element is public. Public elements are visible within
any library |
| 3104 * that imports the library in which they are declared. |
| 3105 * |
| 3106 * @return `true` if this element is public |
| 3107 */ |
| 3108 bool get isPublic; |
| 3109 |
| 3110 /** |
| 3111 * Return `true` if this element is synthetic. A synthetic element is an eleme
nt that is not |
| 3112 * represented in the source code explicitly, but is implied by the source cod
e, such as the |
| 3113 * default constructor for a class that does not explicitly define any constru
ctors. |
| 3114 * |
| 3115 * @return `true` if this element is synthetic |
| 3116 */ |
| 3117 bool get isSynthetic; |
| 3118 |
| 3119 /** |
| 3120 * Use the given visitor to visit all of the children of this element. There i
s no guarantee of |
| 3121 * the order in which the children will be visited. |
| 3122 * |
| 3123 * @param visitor the visitor that will be used to visit the children of this
element |
| 3124 */ |
| 3125 void visitChildren(ElementVisitor visitor); |
| 3126 } |
| 3127 |
| 3128 /** |
| 3129 * The interface `ElementAnnotation` defines the behavior of objects representin
g a single |
| 3130 * annotation associated with an element. |
| 3131 */ |
| 3132 abstract class ElementAnnotation { |
| 3133 /** |
| 3134 * Return the element representing the field, variable, or const constructor b
eing used as an |
| 3135 * annotation. |
| 3136 * |
| 3137 * @return the field, variable, or constructor being used as an annotation |
| 3138 */ |
| 3139 Element get element; |
| 3140 |
| 3141 /** |
| 3142 * Return `true` if this annotation marks the associated element as being depr
ecated. |
| 3143 * |
| 3144 * @return `true` if this annotation marks the associated element as being dep
recated |
| 3145 */ |
| 3146 bool get isDeprecated; |
| 3147 |
| 3148 /** |
| 3149 * Return `true` if this annotation marks the associated method as being expec
ted to |
| 3150 * override an inherited method. |
| 3151 * |
| 3152 * @return `true` if this annotation marks the associated method as overriding
another |
| 3153 * method |
| 3154 */ |
| 3155 bool get isOverride; |
| 3156 |
| 3157 /** |
| 3158 * Return `true` if this annotation marks the associated class as implementing
a proxy |
| 3159 * object. |
| 3160 * |
| 3161 * @return `true` if this annotation marks the associated class as implementin
g a proxy |
| 3162 * object |
| 3163 */ |
| 3164 bool get isProxy; |
| 3165 } |
| 3166 |
| 3167 /** |
| 3168 * Instances of the class `ElementAnnotationImpl` implement an [ElementAnnotatio
n]. |
| 3169 */ |
| 3170 class ElementAnnotationImpl implements ElementAnnotation { |
| 3171 /** |
| 3172 * The element representing the field, variable, or constructor being used as
an annotation. |
| 3173 */ |
| 3174 final Element element; |
| 3175 |
| 3176 /** |
| 3177 * An empty array of annotations. |
| 3178 */ |
| 3179 static List<ElementAnnotationImpl> EMPTY_ARRAY = new List<ElementAnnotationImp
l>(0); |
| 3180 |
| 3181 /** |
| 3182 * The name of the class used to mark an element as being deprecated. |
| 3183 */ |
| 3184 static String _DEPRECATED_CLASS_NAME = "Deprecated"; |
| 3185 |
| 3186 /** |
| 3187 * The name of the top-level variable used to mark an element as being depreca
ted. |
| 3188 */ |
| 3189 static String _DEPRECATED_VARIABLE_NAME = "deprecated"; |
| 3190 |
| 3191 /** |
| 3192 * The name of the top-level variable used to mark a method as being expected
to override an |
| 3193 * inherited method. |
| 3194 */ |
| 3195 static String _OVERRIDE_VARIABLE_NAME = "override"; |
| 3196 |
| 3197 /** |
| 3198 * The name of the top-level variable used to mark a class as implementing a p
roxy object. |
| 3199 */ |
| 3200 static String PROXY_VARIABLE_NAME = "proxy"; |
| 3201 |
| 3202 /** |
| 3203 * Initialize a newly created annotation. |
| 3204 * |
| 3205 * @param element the element representing the field, variable, or constructor
being used as an |
| 3206 * annotation |
| 3207 */ |
| 3208 ElementAnnotationImpl(this.element); |
| 3209 |
| 3210 @override |
| 3211 bool get isDeprecated { |
| 3212 if (element != null) { |
| 3213 LibraryElement library = element.library; |
| 3214 if (library != null && library.isDartCore) { |
| 3215 if (element is ConstructorElement) { |
| 3216 ConstructorElement constructorElement = element as ConstructorElement; |
| 3217 if (constructorElement.enclosingElement.name == _DEPRECATED_CLASS_NAME
) { |
| 3218 return true; |
| 3219 } |
| 3220 } else if (element is PropertyAccessorElement && element.name == _DEPREC
ATED_VARIABLE_NAME) { |
| 3221 return true; |
| 3222 } |
| 3223 } |
| 3224 } |
| 3225 return false; |
| 3226 } |
| 3227 |
| 3228 @override |
| 3229 bool get isOverride { |
| 3230 if (element != null) { |
| 3231 LibraryElement library = element.library; |
| 3232 if (library != null && library.isDartCore) { |
| 3233 if (element is PropertyAccessorElement && element.name == _OVERRIDE_VARI
ABLE_NAME) { |
| 3234 return true; |
| 3235 } |
| 3236 } |
| 3237 } |
| 3238 return false; |
| 3239 } |
| 3240 |
| 3241 @override |
| 3242 bool get isProxy { |
| 3243 if (element != null) { |
| 3244 LibraryElement library = element.library; |
| 3245 if (library != null && library.isDartCore) { |
| 3246 if (element is PropertyAccessorElement && element.name == PROXY_VARIABLE
_NAME) { |
| 3247 return true; |
| 3248 } |
| 3249 } |
| 3250 } |
| 3251 return false; |
| 3252 } |
| 3253 |
| 3254 @override |
| 3255 String toString() => "@${element.toString()}"; |
| 3256 } |
| 3257 |
| 3258 /** |
| 3259 * The abstract class `ElementImpl` implements the behavior common to objects th
at implement |
| 3260 * an [Element]. |
| 3261 */ |
| 3262 abstract class ElementImpl implements Element { |
| 3263 /** |
| 3264 * The enclosing element of this element, or `null` if this element is at the
root of the |
| 3265 * element structure. |
| 3266 */ |
| 3267 ElementImpl _enclosingElement; |
| 3268 |
| 3269 /** |
| 3270 * The name of this element. |
| 3271 */ |
| 3272 String _name; |
| 3273 |
| 3274 /** |
| 3275 * The offset of the name of this element in the file that contains the declar
ation of this |
| 3276 * element. |
| 3277 */ |
| 3278 int nameOffset = 0; |
| 3279 |
| 3280 /** |
| 3281 * A bit-encoded form of the modifiers associated with this element. |
| 3282 */ |
| 3283 int _modifiers = 0; |
| 3284 |
| 3285 /** |
| 3286 * An array containing all of the metadata associated with this element. |
| 3287 */ |
| 3288 List<ElementAnnotation> metadata = ElementAnnotationImpl.EMPTY_ARRAY; |
| 3289 |
| 3290 /** |
| 3291 * A cached copy of the calculated hashCode for this element. |
| 3292 */ |
| 3293 int _cachedHashCode = 0; |
| 3294 |
| 3295 /** |
| 3296 * Initialize a newly created element to have the given name. |
| 3297 * |
| 3298 * @param name the name of this element |
| 3299 */ |
| 3300 ElementImpl.forNode(Identifier name) : this(name == null ? "" : name.name, nam
e == null ? -1 : name.offset); |
| 3301 |
| 3302 /** |
| 3303 * Initialize a newly created element to have the given name. |
| 3304 * |
| 3305 * @param name the name of this element |
| 3306 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 3307 * declaration of this element |
| 3308 */ |
| 3309 ElementImpl(String name, this.nameOffset) { |
| 3310 this._name = StringUtilities.intern(name); |
| 3311 } |
| 3312 |
| 3313 @override |
| 3314 String computeDocumentationComment() { |
| 3315 AnalysisContext context = this.context; |
| 3316 if (context == null) { |
| 3317 return null; |
| 3318 } |
| 3319 return context.computeDocumentationComment(this); |
| 3320 } |
| 3321 |
| 3322 @override |
| 3323 bool operator ==(Object object) { |
| 3324 if (identical(this, object)) { |
| 3325 return true; |
| 3326 } |
| 3327 if (object == null || hashCode != object.hashCode) { |
| 3328 return false; |
| 3329 } |
| 3330 return object.runtimeType == runtimeType && (object as Element).location ==
location; |
| 3331 } |
| 3332 |
| 3333 @override |
| 3334 Element getAncestor(Predicate<Element> predicate) { |
| 3335 Element ancestor = _enclosingElement; |
| 3336 while (ancestor != null && !predicate(ancestor)) { |
| 3337 ancestor = ancestor.enclosingElement; |
| 3338 } |
| 3339 return ancestor; |
| 3340 } |
| 3341 |
| 3342 /** |
| 3343 * Return the child of this element that is uniquely identified by the given i
dentifier, or |
| 3344 * `null` if there is no such child. |
| 3345 * |
| 3346 * @param identifier the identifier used to select a child |
| 3347 * @return the child of this element with the given identifier |
| 3348 */ |
| 3349 ElementImpl getChild(String identifier) => null; |
| 3350 |
| 3351 @override |
| 3352 AnalysisContext get context { |
| 3353 if (_enclosingElement == null) { |
| 3354 return null; |
| 3355 } |
| 3356 return _enclosingElement.context; |
| 3357 } |
| 3358 |
| 3359 @override |
| 3360 String get displayName => _name; |
| 3361 |
| 3362 @override |
| 3363 Element get enclosingElement => _enclosingElement; |
| 3364 |
| 3365 @override |
| 3366 String getExtendedDisplayName(String shortName) { |
| 3367 if (shortName == null) { |
| 3368 shortName = displayName; |
| 3369 } |
| 3370 Source source = this.source; |
| 3371 if (source != null) { |
| 3372 return "${shortName} (${source.fullName})"; |
| 3373 } |
| 3374 return shortName; |
| 3375 } |
| 3376 |
| 3377 @override |
| 3378 LibraryElement get library => getAncestor((element) => element is LibraryEleme
nt); |
| 3379 |
| 3380 @override |
| 3381 ElementLocation get location => new ElementLocationImpl.con1(this); |
| 3382 |
| 3383 @override |
| 3384 String get name => _name; |
| 3385 |
| 3386 @override |
| 3387 AstNode get node => getNodeMatching((node) => node is AstNode); |
| 3388 |
| 3389 @override |
| 3390 Source get source { |
| 3391 if (_enclosingElement == null) { |
| 3392 return null; |
| 3393 } |
| 3394 return _enclosingElement.source; |
| 3395 } |
| 3396 |
| 3397 @override |
| 3398 CompilationUnit get unit => context.resolveCompilationUnit(source, library); |
| 3399 |
| 3400 @override |
| 3401 int get hashCode { |
| 3402 // TODO: We might want to re-visit this optimization in the future. |
| 3403 // We cache the hash code value as this is a very frequently called method. |
| 3404 if (_cachedHashCode == 0) { |
| 3405 int hashIdentifier = identifier.hashCode; |
| 3406 Element enclosing = enclosingElement; |
| 3407 if (enclosing != null) { |
| 3408 _cachedHashCode = hashIdentifier + enclosing.hashCode; |
| 3409 } else { |
| 3410 _cachedHashCode = hashIdentifier; |
| 3411 } |
| 3412 } |
| 3413 return _cachedHashCode; |
| 3414 } |
| 3415 |
| 3416 @override |
| 3417 bool isAccessibleIn(LibraryElement library) { |
| 3418 if (Identifier.isPrivateName(_name)) { |
| 3419 return library == this.library; |
| 3420 } |
| 3421 return true; |
| 3422 } |
| 3423 |
| 3424 @override |
| 3425 bool get isDeprecated { |
| 3426 for (ElementAnnotation annotation in metadata) { |
| 3427 if (annotation.isDeprecated) { |
| 3428 return true; |
| 3429 } |
| 3430 } |
| 3431 return false; |
| 3432 } |
| 3433 |
| 3434 @override |
| 3435 bool get isOverride { |
| 3436 for (ElementAnnotation annotation in metadata) { |
| 3437 if (annotation.isOverride) { |
| 3438 return true; |
| 3439 } |
| 3440 } |
| 3441 return false; |
| 3442 } |
| 3443 |
| 3444 @override |
| 3445 bool get isPrivate { |
| 3446 String name = displayName; |
| 3447 if (name == null) { |
| 3448 return true; |
| 3449 } |
| 3450 return Identifier.isPrivateName(name); |
| 3451 } |
| 3452 |
| 3453 @override |
| 3454 bool get isPublic => !isPrivate; |
| 3455 |
| 3456 @override |
| 3457 bool get isSynthetic => hasModifier(Modifier.SYNTHETIC); |
| 3458 |
| 3459 /** |
| 3460 * Set the enclosing element of this element to the given element. |
| 3461 * |
| 3462 * @param element the enclosing element of this element |
| 3463 */ |
| 3464 void set enclosingElement(Element element) { |
| 3465 _enclosingElement = element as ElementImpl; |
| 3466 } |
| 3467 |
| 3468 /** |
| 3469 * Set whether this element is synthetic to correspond to the given value. |
| 3470 * |
| 3471 * @param isSynthetic `true` if the element is synthetic |
| 3472 */ |
| 3473 void set synthetic(bool isSynthetic) { |
| 3474 setModifier(Modifier.SYNTHETIC, isSynthetic); |
| 3475 } |
| 3476 |
| 3477 @override |
| 3478 String toString() { |
| 3479 JavaStringBuilder builder = new JavaStringBuilder(); |
| 3480 appendTo(builder); |
| 3481 return builder.toString(); |
| 3482 } |
| 3483 |
| 3484 @override |
| 3485 void visitChildren(ElementVisitor visitor) { |
| 3486 } |
| 3487 |
| 3488 /** |
| 3489 * Append a textual representation of this type to the given builder. |
| 3490 * |
| 3491 * @param builder the builder to which the text is to be appended |
| 3492 */ |
| 3493 void appendTo(JavaStringBuilder builder) { |
| 3494 if (_name == null) { |
| 3495 builder.append("<unnamed "); |
| 3496 builder.append(runtimeType.toString()); |
| 3497 builder.append(">"); |
| 3498 } else { |
| 3499 builder.append(_name); |
| 3500 } |
| 3501 } |
| 3502 |
| 3503 /** |
| 3504 * Set this [Element] as an enclosing for given. |
| 3505 * |
| 3506 * @param element the element to enclose, must be [ElementImpl] |
| 3507 */ |
| 3508 void encloseElement(ElementImpl element) { |
| 3509 element.enclosingElement = this; |
| 3510 } |
| 3511 |
| 3512 /** |
| 3513 * Return an identifier that uniquely identifies this element among the childr
en of this element's |
| 3514 * parent. |
| 3515 * |
| 3516 * @return an identifier that uniquely identifies this element relative to its
parent |
| 3517 */ |
| 3518 String get identifier => name; |
| 3519 |
| 3520 /** |
| 3521 * Return the resolved [AstNode] of the given type enclosing [getNameOffset]. |
| 3522 */ |
| 3523 AstNode getNodeMatching(Predicate<AstNode> predicate) { |
| 3524 CompilationUnit unit = this.unit; |
| 3525 if (unit == null) { |
| 3526 return null; |
| 3527 } |
| 3528 int offset = nameOffset; |
| 3529 AstNode node = new NodeLocator.con1(offset).searchWithin(unit); |
| 3530 if (node == null) { |
| 3531 return null; |
| 3532 } |
| 3533 return node.getAncestor(predicate); |
| 3534 } |
| 3535 |
| 3536 /** |
| 3537 * Return `true` if this element has the given modifier associated with it. |
| 3538 * |
| 3539 * @param modifier the modifier being tested for |
| 3540 * @return `true` if this element has the given modifier associated with it |
| 3541 */ |
| 3542 bool hasModifier(Modifier modifier) => BooleanArray.getEnum(_modifiers, modifi
er); |
| 3543 |
| 3544 /** |
| 3545 * If the given child is not `null`, use the given visitor to visit it. |
| 3546 * |
| 3547 * @param child the child to be visited |
| 3548 * @param visitor the visitor to be used to visit the child |
| 3549 */ |
| 3550 void safelyVisitChild(Element child, ElementVisitor visitor) { |
| 3551 if (child != null) { |
| 3552 child.accept(visitor); |
| 3553 } |
| 3554 } |
| 3555 |
| 3556 /** |
| 3557 * Use the given visitor to visit all of the children in the given array. |
| 3558 * |
| 3559 * @param children the children to be visited |
| 3560 * @param visitor the visitor being used to visit the children |
| 3561 */ |
| 3562 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) { |
| 3563 if (children != null) { |
| 3564 for (Element child in children) { |
| 3565 child.accept(visitor); |
| 3566 } |
| 3567 } |
| 3568 } |
| 3569 |
| 3570 /** |
| 3571 * Set whether the given modifier is associated with this element to correspon
d to the given |
| 3572 * value. |
| 3573 * |
| 3574 * @param modifier the modifier to be set |
| 3575 * @param value `true` if the modifier is to be associated with this element |
| 3576 */ |
| 3577 void setModifier(Modifier modifier, bool value) { |
| 3578 _modifiers = BooleanArray.setEnum(_modifiers, modifier, value); |
| 3579 } |
| 3580 } |
| 3581 |
| 3582 /** |
| 3583 * The enumeration `ElementKind` defines the various kinds of elements in the el
ement model. |
| 3584 */ |
| 3585 class ElementKind extends Enum<ElementKind> { |
| 3586 static const ElementKind ANGULAR_FORMATTER = const ElementKind('ANGULAR_FORMAT
TER', 0, "Angular formatter"); |
| 3587 |
| 3588 static const ElementKind ANGULAR_COMPONENT = const ElementKind('ANGULAR_COMPON
ENT', 1, "Angular component"); |
| 3589 |
| 3590 static const ElementKind ANGULAR_CONTROLLER = const ElementKind('ANGULAR_CONTR
OLLER', 2, "Angular controller"); |
| 3591 |
| 3592 static const ElementKind ANGULAR_DIRECTIVE = const ElementKind('ANGULAR_DIRECT
IVE', 3, "Angular directive"); |
| 3593 |
| 3594 static const ElementKind ANGULAR_PROPERTY = const ElementKind('ANGULAR_PROPERT
Y', 4, "Angular property"); |
| 3595 |
| 3596 static const ElementKind ANGULAR_SCOPE_PROPERTY = const ElementKind('ANGULAR_S
COPE_PROPERTY', 5, "Angular scope property"); |
| 3597 |
| 3598 static const ElementKind ANGULAR_SELECTOR = const ElementKind('ANGULAR_SELECTO
R', 6, "Angular selector"); |
| 3599 |
| 3600 static const ElementKind ANGULAR_VIEW = const ElementKind('ANGULAR_VIEW', 7, "
Angular view"); |
| 3601 |
| 3602 static const ElementKind CLASS = const ElementKind('CLASS', 8, "class"); |
| 3603 |
| 3604 static const ElementKind COMPILATION_UNIT = const ElementKind('COMPILATION_UNI
T', 9, "compilation unit"); |
| 3605 |
| 3606 static const ElementKind CONSTRUCTOR = const ElementKind('CONSTRUCTOR', 10, "c
onstructor"); |
| 3607 |
| 3608 static const ElementKind DYNAMIC = const ElementKind('DYNAMIC', 11, "<dynamic>
"); |
| 3609 |
| 3610 static const ElementKind EMBEDDED_HTML_SCRIPT = const ElementKind('EMBEDDED_HT
ML_SCRIPT', 12, "embedded html script"); |
| 3611 |
| 3612 static const ElementKind ERROR = const ElementKind('ERROR', 13, "<error>"); |
| 3613 |
| 3614 static const ElementKind EXPORT = const ElementKind('EXPORT', 14, "export dire
ctive"); |
| 3615 |
| 3616 static const ElementKind EXTERNAL_HTML_SCRIPT = const ElementKind('EXTERNAL_HT
ML_SCRIPT', 15, "external html script"); |
| 3617 |
| 3618 static const ElementKind FIELD = const ElementKind('FIELD', 16, "field"); |
| 3619 |
| 3620 static const ElementKind FUNCTION = const ElementKind('FUNCTION', 17, "functio
n"); |
| 3621 |
| 3622 static const ElementKind GETTER = const ElementKind('GETTER', 18, "getter"); |
| 3623 |
| 3624 static const ElementKind HTML = const ElementKind('HTML', 19, "html"); |
| 3625 |
| 3626 static const ElementKind IMPORT = const ElementKind('IMPORT', 20, "import dire
ctive"); |
| 3627 |
| 3628 static const ElementKind LABEL = const ElementKind('LABEL', 21, "label"); |
| 3629 |
| 3630 static const ElementKind LIBRARY = const ElementKind('LIBRARY', 22, "library")
; |
| 3631 |
| 3632 static const ElementKind LOCAL_VARIABLE = const ElementKind('LOCAL_VARIABLE',
23, "local variable"); |
| 3633 |
| 3634 static const ElementKind METHOD = const ElementKind('METHOD', 24, "method"); |
| 3635 |
| 3636 static const ElementKind NAME = const ElementKind('NAME', 25, "<name>"); |
| 3637 |
| 3638 static const ElementKind PARAMETER = const ElementKind('PARAMETER', 26, "param
eter"); |
| 3639 |
| 3640 static const ElementKind POLYMER_ATTRIBUTE = const ElementKind('POLYMER_ATTRIB
UTE', 27, "Polymer attribute"); |
| 3641 |
| 3642 static const ElementKind POLYMER_TAG_DART = const ElementKind('POLYMER_TAG_DAR
T', 28, "Polymer Dart tag"); |
| 3643 |
| 3644 static const ElementKind POLYMER_TAG_HTML = const ElementKind('POLYMER_TAG_HTM
L', 29, "Polymer HTML tag"); |
| 3645 |
| 3646 static const ElementKind PREFIX = const ElementKind('PREFIX', 30, "import pref
ix"); |
| 3647 |
| 3648 static const ElementKind SETTER = const ElementKind('SETTER', 31, "setter"); |
| 3649 |
| 3650 static const ElementKind TOP_LEVEL_VARIABLE = const ElementKind('TOP_LEVEL_VAR
IABLE', 32, "top level variable"); |
| 3651 |
| 3652 static const ElementKind FUNCTION_TYPE_ALIAS = const ElementKind('FUNCTION_TYP
E_ALIAS', 33, "function type alias"); |
| 3653 |
| 3654 static const ElementKind TYPE_PARAMETER = const ElementKind('TYPE_PARAMETER',
34, "type parameter"); |
| 3655 |
| 3656 static const ElementKind UNIVERSE = const ElementKind('UNIVERSE', 35, "<univer
se>"); |
| 3657 |
| 3658 static const List<ElementKind> values = const [ |
| 3659 ANGULAR_FORMATTER, |
| 3660 ANGULAR_COMPONENT, |
| 3661 ANGULAR_CONTROLLER, |
| 3662 ANGULAR_DIRECTIVE, |
| 3663 ANGULAR_PROPERTY, |
| 3664 ANGULAR_SCOPE_PROPERTY, |
| 3665 ANGULAR_SELECTOR, |
| 3666 ANGULAR_VIEW, |
| 3667 CLASS, |
| 3668 COMPILATION_UNIT, |
| 3669 CONSTRUCTOR, |
| 3670 DYNAMIC, |
| 3671 EMBEDDED_HTML_SCRIPT, |
| 3672 ERROR, |
| 3673 EXPORT, |
| 3674 EXTERNAL_HTML_SCRIPT, |
| 3675 FIELD, |
| 3676 FUNCTION, |
| 3677 GETTER, |
| 3678 HTML, |
| 3679 IMPORT, |
| 3680 LABEL, |
| 3681 LIBRARY, |
| 3682 LOCAL_VARIABLE, |
| 3683 METHOD, |
| 3684 NAME, |
| 3685 PARAMETER, |
| 3686 POLYMER_ATTRIBUTE, |
| 3687 POLYMER_TAG_DART, |
| 3688 POLYMER_TAG_HTML, |
| 3689 PREFIX, |
| 3690 SETTER, |
| 3691 TOP_LEVEL_VARIABLE, |
| 3692 FUNCTION_TYPE_ALIAS, |
| 3693 TYPE_PARAMETER, |
| 3694 UNIVERSE]; |
| 3695 |
| 3696 /** |
| 3697 * Return the kind of the given element, or [ERROR] if the element is `null`.
This is |
| 3698 * a utility method that can reduce the need for null checks in other places. |
| 3699 * |
| 3700 * @param element the element whose kind is to be returned |
| 3701 * @return the kind of the given element |
| 3702 */ |
| 3703 static ElementKind of(Element element) { |
| 3704 if (element == null) { |
| 3705 return ERROR; |
| 3706 } |
| 3707 return element.kind; |
| 3708 } |
| 3709 |
| 3710 /** |
| 3711 * The name displayed in the UI for this kind of element. |
| 3712 */ |
| 3713 final String displayName; |
| 3714 |
| 3715 /** |
| 3716 * Initialize a newly created element kind to have the given display name. |
| 3717 * |
| 3718 * @param displayName the name displayed in the UI for this kind of element |
| 3719 */ |
| 3720 const ElementKind(String name, int ordinal, this.displayName) : super(name, or
dinal); |
| 3721 } |
| 3722 |
| 3723 /** |
| 3724 * The interface `ElementLocation` defines the behavior of objects that represen
t the location |
| 3725 * of an element within the element model. |
| 3726 */ |
| 3727 abstract class ElementLocation { |
| 3728 /** |
| 3729 * Return the path to the element whose location is represented by this object
. Clients must not |
| 3730 * modify the returned array. |
| 3731 * |
| 3732 * @return the path to the element whose location is represented by this objec
t |
| 3733 */ |
| 3734 List<String> get components; |
| 3735 |
| 3736 /** |
| 3737 * Return an encoded representation of this location that can be used to creat
e a location that is |
| 3738 * equal to this location. |
| 3739 * |
| 3740 * @return an encoded representation of this location |
| 3741 */ |
| 3742 String get encoding; |
| 3743 } |
| 3744 |
| 3745 /** |
| 3746 * Instances of the class `ElementLocationImpl` implement an [ElementLocation]. |
| 3747 */ |
| 3748 class ElementLocationImpl implements ElementLocation { |
| 3749 /** |
| 3750 * The path to the element whose location is represented by this object. |
| 3751 */ |
| 3752 List<String> _components; |
| 3753 |
| 3754 /** |
| 3755 * The character used to separate components in the encoded form. |
| 3756 */ |
| 3757 static int _SEPARATOR_CHAR = 0x3B; |
| 3758 |
| 3759 /** |
| 3760 * Initialize a newly created location to represent the given element. |
| 3761 * |
| 3762 * @param element the element whose location is being represented |
| 3763 */ |
| 3764 ElementLocationImpl.con1(Element element) { |
| 3765 List<String> components = new List<String>(); |
| 3766 Element ancestor = element; |
| 3767 while (ancestor != null) { |
| 3768 components.insert(0, (ancestor as ElementImpl).identifier); |
| 3769 ancestor = ancestor.enclosingElement; |
| 3770 } |
| 3771 this._components = new List.from(components); |
| 3772 } |
| 3773 |
| 3774 /** |
| 3775 * Initialize a newly created location from the given encoded form. |
| 3776 * |
| 3777 * @param encoding the encoded form of a location |
| 3778 */ |
| 3779 ElementLocationImpl.con2(String encoding) { |
| 3780 this._components = _decode(encoding); |
| 3781 } |
| 3782 |
| 3783 /** |
| 3784 * Initialize a newly created location from the given components. |
| 3785 * |
| 3786 * @param components the components of a location |
| 3787 */ |
| 3788 ElementLocationImpl.con3(List<String> components) { |
| 3789 this._components = components; |
| 3790 } |
| 3791 |
| 3792 @override |
| 3793 bool operator ==(Object object) { |
| 3794 if (identical(this, object)) { |
| 3795 return true; |
| 3796 } |
| 3797 if (object is! ElementLocationImpl) { |
| 3798 return false; |
| 3799 } |
| 3800 ElementLocationImpl location = object as ElementLocationImpl; |
| 3801 List<String> otherComponents = location._components; |
| 3802 int length = _components.length; |
| 3803 if (otherComponents.length != length) { |
| 3804 return false; |
| 3805 } |
| 3806 for (int i = 0; i < length; i++) { |
| 3807 if (_components[i] != otherComponents[i]) { |
| 3808 return false; |
| 3809 } |
| 3810 } |
| 3811 return true; |
| 3812 } |
| 3813 |
| 3814 @override |
| 3815 List<String> get components => _components; |
| 3816 |
| 3817 @override |
| 3818 String get encoding { |
| 3819 JavaStringBuilder builder = new JavaStringBuilder(); |
| 3820 int length = _components.length; |
| 3821 for (int i = 0; i < length; i++) { |
| 3822 if (i > 0) { |
| 3823 builder.appendChar(_SEPARATOR_CHAR); |
| 3824 } |
| 3825 _encode(builder, _components[i]); |
| 3826 } |
| 3827 return builder.toString(); |
| 3828 } |
| 3829 |
| 3830 @override |
| 3831 int get hashCode { |
| 3832 int result = 1; |
| 3833 for (int i = 0; i < _components.length; i++) { |
| 3834 String component = _components[i]; |
| 3835 result = 31 * result + component.hashCode; |
| 3836 } |
| 3837 return result; |
| 3838 } |
| 3839 |
| 3840 @override |
| 3841 String toString() => encoding; |
| 3842 |
| 3843 /** |
| 3844 * Decode the encoded form of a location into an array of components. |
| 3845 * |
| 3846 * @param encoding the encoded form of a location |
| 3847 * @return the components that were encoded |
| 3848 */ |
| 3849 List<String> _decode(String encoding) { |
| 3850 List<String> components = new List<String>(); |
| 3851 JavaStringBuilder builder = new JavaStringBuilder(); |
| 3852 int index = 0; |
| 3853 int length = encoding.length; |
| 3854 while (index < length) { |
| 3855 int currentChar = encoding.codeUnitAt(index); |
| 3856 if (currentChar == _SEPARATOR_CHAR) { |
| 3857 if (index + 1 < length && encoding.codeUnitAt(index + 1) == _SEPARATOR_C
HAR) { |
| 3858 builder.appendChar(_SEPARATOR_CHAR); |
| 3859 index += 2; |
| 3860 } else { |
| 3861 components.add(builder.toString()); |
| 3862 builder.length = 0; |
| 3863 index++; |
| 3864 } |
| 3865 } else { |
| 3866 builder.appendChar(currentChar); |
| 3867 index++; |
| 3868 } |
| 3869 } |
| 3870 components.add(builder.toString()); |
| 3871 return new List.from(components); |
| 3872 } |
| 3873 |
| 3874 /** |
| 3875 * Append an encoded form of the given component to the given builder. |
| 3876 * |
| 3877 * @param builder the builder to which the encoded component is to be appended |
| 3878 * @param component the component to be appended to the builder |
| 3879 */ |
| 3880 void _encode(JavaStringBuilder builder, String component) { |
| 3881 int length = component.length; |
| 3882 for (int i = 0; i < length; i++) { |
| 3883 int currentChar = component.codeUnitAt(i); |
| 3884 if (currentChar == _SEPARATOR_CHAR) { |
| 3885 builder.appendChar(_SEPARATOR_CHAR); |
| 3886 } |
| 3887 builder.appendChar(currentChar); |
| 3888 } |
| 3889 } |
| 3890 } |
| 3891 |
| 3892 /** |
| 3893 * The class `ElementPair` is a pair of [Element]s. [Object#equals] and |
| 3894 * [Object#hashCode] so this class can be used in hashed data structures. |
| 3895 */ |
| 3896 class ElementPair { |
| 3897 /** |
| 3898 * The first [Element] |
| 3899 */ |
| 3900 final Element _first; |
| 3901 |
| 3902 /** |
| 3903 * The second [Element] |
| 3904 */ |
| 3905 final Element _second; |
| 3906 |
| 3907 /** |
| 3908 * The sole constructor for this class, taking two [Element]s. |
| 3909 * |
| 3910 * @param first the first element |
| 3911 * @param second the second element |
| 3912 */ |
| 3913 ElementPair(this._first, this._second); |
| 3914 |
| 3915 @override |
| 3916 bool operator ==(Object object) { |
| 3917 if (identical(object, this)) { |
| 3918 return true; |
| 3919 } |
| 3920 if (object is ElementPair) { |
| 3921 ElementPair elementPair = object; |
| 3922 return (_first == elementPair._first) && (_second == elementPair._second); |
| 3923 } |
| 3924 return false; |
| 3925 } |
| 3926 |
| 3927 /** |
| 3928 * Return the first element. |
| 3929 * |
| 3930 * @return the first element |
| 3931 */ |
| 3932 Element get firstElt => _first; |
| 3933 |
| 3934 /** |
| 3935 * Return the second element |
| 3936 * |
| 3937 * @return the second element |
| 3938 */ |
| 3939 Element get secondElt => _second; |
| 3940 |
| 3941 @override |
| 3942 int get hashCode => ObjectUtilities.combineHashCodes(_first.hashCode, _second.
hashCode); |
| 3943 } |
| 3944 |
| 3945 /** |
| 3946 * The interface `ElementVisitor` defines the behavior of objects that can be us
ed to visit an |
| 3947 * element structure. |
| 3948 */ |
| 3949 abstract class ElementVisitor<R> { |
| 3950 R visitAngularComponentElement(AngularComponentElement element); |
| 3951 |
| 3952 R visitAngularControllerElement(AngularControllerElement element); |
| 3953 |
| 3954 R visitAngularDirectiveElement(AngularDecoratorElement element); |
| 3955 |
| 3956 R visitAngularFormatterElement(AngularFormatterElement element); |
| 3957 |
| 3958 R visitAngularPropertyElement(AngularPropertyElement element); |
| 3959 |
| 3960 R visitAngularScopePropertyElement(AngularScopePropertyElement element); |
| 3961 |
| 3962 R visitAngularSelectorElement(AngularSelectorElement element); |
| 3963 |
| 3964 R visitAngularViewElement(AngularViewElement element); |
| 3965 |
| 3966 R visitClassElement(ClassElement element); |
| 3967 |
| 3968 R visitCompilationUnitElement(CompilationUnitElement element); |
| 3969 |
| 3970 R visitConstructorElement(ConstructorElement element); |
| 3971 |
| 3972 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element); |
| 3973 |
| 3974 R visitExportElement(ExportElement element); |
| 3975 |
| 3976 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element); |
| 3977 |
| 3978 R visitFieldElement(FieldElement element); |
| 3979 |
| 3980 R visitFieldFormalParameterElement(FieldFormalParameterElement element); |
| 3981 |
| 3982 R visitFunctionElement(FunctionElement element); |
| 3983 |
| 3984 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element); |
| 3985 |
| 3986 R visitHtmlElement(HtmlElement element); |
| 3987 |
| 3988 R visitImportElement(ImportElement element); |
| 3989 |
| 3990 R visitLabelElement(LabelElement element); |
| 3991 |
| 3992 R visitLibraryElement(LibraryElement element); |
| 3993 |
| 3994 R visitLocalVariableElement(LocalVariableElement element); |
| 3995 |
| 3996 R visitMethodElement(MethodElement element); |
| 3997 |
| 3998 R visitMultiplyDefinedElement(MultiplyDefinedElement element); |
| 3999 |
| 4000 R visitParameterElement(ParameterElement element); |
| 4001 |
| 4002 R visitPolymerAttributeElement(PolymerAttributeElement element); |
| 4003 |
| 4004 R visitPolymerTagDartElement(PolymerTagDartElement element); |
| 4005 |
| 4006 R visitPolymerTagHtmlElement(PolymerTagHtmlElement element); |
| 4007 |
| 4008 R visitPrefixElement(PrefixElement element); |
| 4009 |
| 4010 R visitPropertyAccessorElement(PropertyAccessorElement element); |
| 4011 |
| 4012 R visitTopLevelVariableElement(TopLevelVariableElement element); |
| 4013 |
| 4014 R visitTypeParameterElement(TypeParameterElement element); |
| 4015 } |
| 4016 |
| 4017 /** |
| 4018 * The interface `EmbeddedHtmlScriptElement` defines the behavior of elements re
presenting a |
| 4019 * script tag in an HTML file having content that defines a Dart library. |
| 4020 */ |
| 4021 abstract class EmbeddedHtmlScriptElement implements HtmlScriptElement { |
| 4022 /** |
| 4023 * Return the library element defined by the content of the script tag. |
| 4024 * |
| 4025 * @return the library element (not `null`) |
| 4026 */ |
| 4027 LibraryElement get scriptLibrary; |
| 4028 } |
| 4029 |
| 4030 /** |
| 4031 * Instances of the class `EmbeddedHtmlScriptElementImpl` implement an |
| 4032 * [EmbeddedHtmlScriptElement]. |
| 4033 */ |
| 4034 class EmbeddedHtmlScriptElementImpl extends HtmlScriptElementImpl implements Emb
eddedHtmlScriptElement { |
| 4035 /** |
| 4036 * The library defined by the script tag's content. |
| 4037 */ |
| 4038 LibraryElement _scriptLibrary; |
| 4039 |
| 4040 /** |
| 4041 * Initialize a newly created script element to have the specified tag name an
d offset. |
| 4042 * |
| 4043 * @param node the XML node from which this element is derived (not `null`) |
| 4044 */ |
| 4045 EmbeddedHtmlScriptElementImpl(XmlTagNode node) : super(node); |
| 4046 |
| 4047 @override |
| 4048 accept(ElementVisitor visitor) => visitor.visitEmbeddedHtmlScriptElement(this)
; |
| 4049 |
| 4050 @override |
| 4051 ElementKind get kind => ElementKind.EMBEDDED_HTML_SCRIPT; |
| 4052 |
| 4053 @override |
| 4054 LibraryElement get scriptLibrary => _scriptLibrary; |
| 4055 |
| 4056 /** |
| 4057 * Set the script library defined by the script tag's content. |
| 4058 * |
| 4059 * @param scriptLibrary the library or `null` if none |
| 4060 */ |
| 4061 void set scriptLibrary(LibraryElementImpl scriptLibrary) { |
| 4062 scriptLibrary.enclosingElement = this; |
| 4063 this._scriptLibrary = scriptLibrary; |
| 4064 } |
| 4065 |
| 4066 @override |
| 4067 void visitChildren(ElementVisitor visitor) { |
| 4068 safelyVisitChild(_scriptLibrary, visitor); |
| 4069 } |
| 4070 } |
| 4071 |
| 4072 /** |
| 4073 * The interface `ExecutableElement` defines the behavior of elements representi
ng an |
| 4074 * executable object, including functions, methods, constructors, getters, and s
etters. |
| 4075 */ |
| 4076 abstract class ExecutableElement implements Element { |
| 4077 /** |
| 4078 * Return an array containing all of the functions defined within this executa
ble element. |
| 4079 * |
| 4080 * @return the functions defined within this executable element |
| 4081 */ |
| 4082 List<FunctionElement> get functions; |
| 4083 |
| 4084 /** |
| 4085 * Return an array containing all of the labels defined within this executable
element. |
| 4086 * |
| 4087 * @return the labels defined within this executable element |
| 4088 */ |
| 4089 List<LabelElement> get labels; |
| 4090 |
| 4091 /** |
| 4092 * Return an array containing all of the local variables defined within this e
xecutable element. |
| 4093 * |
| 4094 * @return the local variables defined within this executable element |
| 4095 */ |
| 4096 List<LocalVariableElement> get localVariables; |
| 4097 |
| 4098 /** |
| 4099 * Return an array containing all of the parameters defined by this executable
element. |
| 4100 * |
| 4101 * @return the parameters defined by this executable element |
| 4102 */ |
| 4103 List<ParameterElement> get parameters; |
| 4104 |
| 4105 /** |
| 4106 * Return the return type defined by this executable element. |
| 4107 * |
| 4108 * @return the return type defined by this executable element |
| 4109 */ |
| 4110 DartType get returnType; |
| 4111 |
| 4112 /** |
| 4113 * Return the type of function defined by this executable element. |
| 4114 * |
| 4115 * @return the type of function defined by this executable element |
| 4116 */ |
| 4117 FunctionType get type; |
| 4118 |
| 4119 /** |
| 4120 * Return `true` if this executable element has body marked as being asynchron
ous. |
| 4121 * |
| 4122 * @return `true` if this executable element has body marked as being asynchro
nous |
| 4123 */ |
| 4124 bool get isAsynchronous; |
| 4125 |
| 4126 /** |
| 4127 * Return `true` if this executable element has a body marked as being a gener
ator. |
| 4128 * |
| 4129 * @return `true` if this executable element has a body marked as being a gene
rator |
| 4130 */ |
| 4131 bool get isGenerator; |
| 4132 |
| 4133 /** |
| 4134 * Return `true` if this executable element is an operator. The test may be ba
sed on the |
| 4135 * name of the executable element, in which case the result will be correct wh
en the name is |
| 4136 * legal. |
| 4137 * |
| 4138 * @return `true` if this executable element is an operator |
| 4139 */ |
| 4140 bool get isOperator; |
| 4141 |
| 4142 /** |
| 4143 * Return `true` if this element is a static element. A static element is an e
lement that is |
| 4144 * not associated with a particular instance, but rather with an entire librar
y or class. |
| 4145 * |
| 4146 * @return `true` if this executable element is a static element |
| 4147 */ |
| 4148 bool get isStatic; |
| 4149 |
| 4150 /** |
| 4151 * Return `true` if this executable element has a body marked as being synchro
nous. |
| 4152 * |
| 4153 * @return `true` if this executable element has a body marked as being synchr
onous |
| 4154 */ |
| 4155 bool get isSynchronous; |
| 4156 } |
| 4157 |
| 4158 /** |
| 4159 * The abstract class `ExecutableElementImpl` implements the behavior common to |
| 4160 * `ExecutableElement`s. |
| 4161 */ |
| 4162 abstract class ExecutableElementImpl extends ElementImpl implements ExecutableEl
ement { |
| 4163 /** |
| 4164 * An array containing all of the functions defined within this executable ele
ment. |
| 4165 */ |
| 4166 List<FunctionElement> _functions = FunctionElementImpl.EMPTY_ARRAY; |
| 4167 |
| 4168 /** |
| 4169 * An array containing all of the labels defined within this executable elemen
t. |
| 4170 */ |
| 4171 List<LabelElement> _labels = LabelElementImpl.EMPTY_ARRAY; |
| 4172 |
| 4173 /** |
| 4174 * An array containing all of the local variables defined within this executab
le element. |
| 4175 */ |
| 4176 List<LocalVariableElement> _localVariables = LocalVariableElementImpl.EMPTY_AR
RAY; |
| 4177 |
| 4178 /** |
| 4179 * An array containing all of the parameters defined by this executable elemen
t. |
| 4180 */ |
| 4181 List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY; |
| 4182 |
| 4183 /** |
| 4184 * The return type defined by this executable element. |
| 4185 */ |
| 4186 DartType returnType; |
| 4187 |
| 4188 /** |
| 4189 * The type of function defined by this executable element. |
| 4190 */ |
| 4191 FunctionType type; |
| 4192 |
| 4193 /** |
| 4194 * An empty array of executable elements. |
| 4195 */ |
| 4196 static List<ExecutableElement> EMPTY_ARRAY = new List<ExecutableElement>(0); |
| 4197 |
| 4198 /** |
| 4199 * Initialize a newly created executable element to have the given name. |
| 4200 * |
| 4201 * @param name the name of this element |
| 4202 */ |
| 4203 ExecutableElementImpl.forNode(Identifier name) : super.forNode(name); |
| 4204 |
| 4205 /** |
| 4206 * Initialize a newly created executable element to have the given name. |
| 4207 * |
| 4208 * @param name the name of this element |
| 4209 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 4210 * declaration of this element |
| 4211 */ |
| 4212 ExecutableElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 4213 |
| 4214 @override |
| 4215 ElementImpl getChild(String identifier) { |
| 4216 for (ExecutableElement function in _functions) { |
| 4217 if ((function as ExecutableElementImpl).identifier == identifier) { |
| 4218 return function as ExecutableElementImpl; |
| 4219 } |
| 4220 } |
| 4221 for (LabelElement label in _labels) { |
| 4222 if ((label as LabelElementImpl).identifier == identifier) { |
| 4223 return label as LabelElementImpl; |
| 4224 } |
| 4225 } |
| 4226 for (VariableElement variable in _localVariables) { |
| 4227 if ((variable as VariableElementImpl).identifier == identifier) { |
| 4228 return variable as VariableElementImpl; |
| 4229 } |
| 4230 } |
| 4231 for (ParameterElement parameter in _parameters) { |
| 4232 if ((parameter as ParameterElementImpl).identifier == identifier) { |
| 4233 return parameter as ParameterElementImpl; |
| 4234 } |
| 4235 } |
| 4236 return null; |
| 4237 } |
| 4238 |
| 4239 @override |
| 4240 List<FunctionElement> get functions => _functions; |
| 4241 |
| 4242 @override |
| 4243 List<LabelElement> get labels => _labels; |
| 4244 |
| 4245 @override |
| 4246 List<LocalVariableElement> get localVariables => _localVariables; |
| 4247 |
| 4248 @override |
| 4249 List<ParameterElement> get parameters => _parameters; |
| 4250 |
| 4251 @override |
| 4252 bool get isAsynchronous => hasModifier(Modifier.ASYNCHRONOUS); |
| 4253 |
| 4254 @override |
| 4255 bool get isGenerator => hasModifier(Modifier.GENERATOR); |
| 4256 |
| 4257 @override |
| 4258 bool get isOperator => false; |
| 4259 |
| 4260 @override |
| 4261 bool get isSynchronous => !hasModifier(Modifier.ASYNCHRONOUS); |
| 4262 |
| 4263 /** |
| 4264 * Set whether this method's body is asynchronous to correspond to the given v
alue. |
| 4265 * |
| 4266 * @param isAsynchronous `true` if the method's body is asynchronous |
| 4267 */ |
| 4268 void set asynchronous(bool isAsynchronous) { |
| 4269 setModifier(Modifier.ASYNCHRONOUS, isAsynchronous); |
| 4270 } |
| 4271 |
| 4272 /** |
| 4273 * Set the functions defined within this executable element to the given funct
ions. |
| 4274 * |
| 4275 * @param functions the functions defined within this executable element |
| 4276 */ |
| 4277 void set functions(List<FunctionElement> functions) { |
| 4278 for (FunctionElement function in functions) { |
| 4279 (function as FunctionElementImpl).enclosingElement = this; |
| 4280 } |
| 4281 this._functions = functions; |
| 4282 } |
| 4283 |
| 4284 /** |
| 4285 * Set whether this method's body is a generator to correspond to the given va
lue. |
| 4286 * |
| 4287 * @param isGenerator `true` if the method's body is a generator |
| 4288 */ |
| 4289 void set generator(bool isGenerator) { |
| 4290 setModifier(Modifier.GENERATOR, isGenerator); |
| 4291 } |
| 4292 |
| 4293 /** |
| 4294 * Set the labels defined within this executable element to the given labels. |
| 4295 * |
| 4296 * @param labels the labels defined within this executable element |
| 4297 */ |
| 4298 void set labels(List<LabelElement> labels) { |
| 4299 for (LabelElement label in labels) { |
| 4300 (label as LabelElementImpl).enclosingElement = this; |
| 4301 } |
| 4302 this._labels = labels; |
| 4303 } |
| 4304 |
| 4305 /** |
| 4306 * Set the local variables defined within this executable element to the given
variables. |
| 4307 * |
| 4308 * @param localVariables the local variables defined within this executable el
ement |
| 4309 */ |
| 4310 void set localVariables(List<LocalVariableElement> localVariables) { |
| 4311 for (LocalVariableElement variable in localVariables) { |
| 4312 (variable as LocalVariableElementImpl).enclosingElement = this; |
| 4313 } |
| 4314 this._localVariables = localVariables; |
| 4315 } |
| 4316 |
| 4317 /** |
| 4318 * Set the parameters defined by this executable element to the given paramete
rs. |
| 4319 * |
| 4320 * @param parameters the parameters defined by this executable element |
| 4321 */ |
| 4322 void set parameters(List<ParameterElement> parameters) { |
| 4323 for (ParameterElement parameter in parameters) { |
| 4324 (parameter as ParameterElementImpl).enclosingElement = this; |
| 4325 } |
| 4326 this._parameters = parameters; |
| 4327 } |
| 4328 |
| 4329 @override |
| 4330 void visitChildren(ElementVisitor visitor) { |
| 4331 super.visitChildren(visitor); |
| 4332 safelyVisitChildren(_functions, visitor); |
| 4333 safelyVisitChildren(_labels, visitor); |
| 4334 safelyVisitChildren(_localVariables, visitor); |
| 4335 safelyVisitChildren(_parameters, visitor); |
| 4336 } |
| 4337 |
| 4338 @override |
| 4339 void appendTo(JavaStringBuilder builder) { |
| 4340 if (this.kind != ElementKind.GETTER) { |
| 4341 builder.append("("); |
| 4342 String closing = null; |
| 4343 ParameterKind kind = ParameterKind.REQUIRED; |
| 4344 int parameterCount = _parameters.length; |
| 4345 for (int i = 0; i < parameterCount; i++) { |
| 4346 if (i > 0) { |
| 4347 builder.append(", "); |
| 4348 } |
| 4349 ParameterElementImpl parameter = _parameters[i] as ParameterElementImpl; |
| 4350 ParameterKind parameterKind = parameter.parameterKind; |
| 4351 if (parameterKind != kind) { |
| 4352 if (closing != null) { |
| 4353 builder.append(closing); |
| 4354 } |
| 4355 if (parameterKind == ParameterKind.POSITIONAL) { |
| 4356 builder.append("["); |
| 4357 closing = "]"; |
| 4358 } else if (parameterKind == ParameterKind.NAMED) { |
| 4359 builder.append("{"); |
| 4360 closing = "}"; |
| 4361 } else { |
| 4362 closing = null; |
| 4363 } |
| 4364 } |
| 4365 kind = parameterKind; |
| 4366 parameter.appendToWithoutDelimiters(builder); |
| 4367 } |
| 4368 if (closing != null) { |
| 4369 builder.append(closing); |
| 4370 } |
| 4371 builder.append(")"); |
| 4372 } |
| 4373 if (type != null) { |
| 4374 builder.append(Element.RIGHT_ARROW); |
| 4375 builder.append(type.returnType); |
| 4376 } |
| 4377 } |
| 4378 } |
| 4379 |
| 4380 /** |
| 4381 * The abstract class `ExecutableMember` defines the behavior common to members
that represent |
| 4382 * an executable element defined in a parameterized type where the values of the
type parameters are |
| 4383 * known. |
| 4384 */ |
| 4385 abstract class ExecutableMember extends Member implements ExecutableElement { |
| 4386 /** |
| 4387 * Initialize a newly created element to represent an executable element of th
e given |
| 4388 * parameterized type. |
| 4389 * |
| 4390 * @param baseElement the element on which the parameterized element was creat
ed |
| 4391 * @param definingType the type in which the element is defined |
| 4392 */ |
| 4393 ExecutableMember(ExecutableElement baseElement, InterfaceType definingType) :
super(baseElement, definingType); |
| 4394 |
| 4395 @override |
| 4396 ExecutableElement get baseElement => super.baseElement as ExecutableElement; |
| 4397 |
| 4398 @override |
| 4399 List<FunctionElement> get functions { |
| 4400 // |
| 4401 // Elements within this element should have type parameters substituted, jus
t like this element. |
| 4402 // |
| 4403 throw new UnsupportedOperationException(); |
| 4404 } |
| 4405 |
| 4406 @override |
| 4407 List<LabelElement> get labels => baseElement.labels; |
| 4408 |
| 4409 @override |
| 4410 List<LocalVariableElement> get localVariables { |
| 4411 // |
| 4412 // Elements within this element should have type parameters substituted, jus
t like this element. |
| 4413 // |
| 4414 throw new UnsupportedOperationException(); |
| 4415 } |
| 4416 |
| 4417 @override |
| 4418 List<ParameterElement> get parameters { |
| 4419 List<ParameterElement> baseParameters = baseElement.parameters; |
| 4420 int parameterCount = baseParameters.length; |
| 4421 if (parameterCount == 0) { |
| 4422 return baseParameters; |
| 4423 } |
| 4424 List<ParameterElement> parameterizedParameters = new List<ParameterElement>(
parameterCount); |
| 4425 for (int i = 0; i < parameterCount; i++) { |
| 4426 parameterizedParameters[i] = ParameterMember.from(baseParameters[i], defin
ingType); |
| 4427 } |
| 4428 return parameterizedParameters; |
| 4429 } |
| 4430 |
| 4431 @override |
| 4432 DartType get returnType => substituteFor(baseElement.returnType); |
| 4433 |
| 4434 @override |
| 4435 FunctionType get type => substituteFor(baseElement.type); |
| 4436 |
| 4437 @override |
| 4438 bool get isAsynchronous => baseElement.isAsynchronous; |
| 4439 |
| 4440 @override |
| 4441 bool get isGenerator => baseElement.isGenerator; |
| 4442 |
| 4443 @override |
| 4444 bool get isOperator => baseElement.isOperator; |
| 4445 |
| 4446 @override |
| 4447 bool get isStatic => baseElement.isStatic; |
| 4448 |
| 4449 @override |
| 4450 bool get isSynchronous => baseElement.isSynchronous; |
| 4451 |
| 4452 @override |
| 4453 void visitChildren(ElementVisitor visitor) { |
| 4454 // TODO(brianwilkerson) We need to finish implementing the accessors used be
low so that we can |
| 4455 // safely invoke them. |
| 4456 super.visitChildren(visitor); |
| 4457 safelyVisitChildren(baseElement.functions, visitor); |
| 4458 safelyVisitChildren(labels, visitor); |
| 4459 safelyVisitChildren(baseElement.localVariables, visitor); |
| 4460 safelyVisitChildren(parameters, visitor); |
| 4461 } |
| 4462 } |
| 4463 |
| 4464 /** |
| 4465 * The interface `ExportElement` defines the behavior of objects representing in
formation |
| 4466 * about a single export directive within a library. |
| 4467 */ |
| 4468 abstract class ExportElement implements Element, UriReferencedElement { |
| 4469 /** |
| 4470 * An empty array of export elements. |
| 4471 */ |
| 4472 static final List<ExportElement> EMPTY_ARRAY = new List<ExportElement>(0); |
| 4473 |
| 4474 /** |
| 4475 * Return an array containing the combinators that were specified as part of t
he export directive |
| 4476 * in the order in which they were specified. |
| 4477 * |
| 4478 * @return the combinators specified in the export directive |
| 4479 */ |
| 4480 List<NamespaceCombinator> get combinators; |
| 4481 |
| 4482 /** |
| 4483 * Return the library that is exported from this library by this export direct
ive. |
| 4484 * |
| 4485 * @return the library that is exported from this library |
| 4486 */ |
| 4487 LibraryElement get exportedLibrary; |
| 4488 } |
| 4489 |
| 4490 /** |
| 4491 * Instances of the class `ExportElementImpl` implement an [ExportElement]. |
| 4492 */ |
| 4493 class ExportElementImpl extends UriReferencedElementImpl implements ExportElemen
t { |
| 4494 /** |
| 4495 * The library that is exported from this library by this export directive. |
| 4496 */ |
| 4497 LibraryElement exportedLibrary; |
| 4498 |
| 4499 /** |
| 4500 * The combinators that were specified as part of the export directive in the
order in which they |
| 4501 * were specified. |
| 4502 */ |
| 4503 List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_ARRAY; |
| 4504 |
| 4505 /** |
| 4506 * Initialize a newly created export element. |
| 4507 */ |
| 4508 ExportElementImpl() : super(null, -1); |
| 4509 |
| 4510 @override |
| 4511 accept(ElementVisitor visitor) => visitor.visitExportElement(this); |
| 4512 |
| 4513 @override |
| 4514 ElementKind get kind => ElementKind.EXPORT; |
| 4515 |
| 4516 @override |
| 4517 void appendTo(JavaStringBuilder builder) { |
| 4518 builder.append("export "); |
| 4519 (exportedLibrary as LibraryElementImpl).appendTo(builder); |
| 4520 } |
| 4521 |
| 4522 @override |
| 4523 String get identifier => exportedLibrary.name; |
| 4524 } |
| 4525 |
| 4526 /** |
| 4527 * The interface `ExternalHtmlScriptElement` defines the behavior of elements re
presenting a |
| 4528 * script tag in an HTML file having a `source` attribute that references a Dart
library |
| 4529 * source file. |
| 4530 */ |
| 4531 abstract class ExternalHtmlScriptElement implements HtmlScriptElement { |
| 4532 /** |
| 4533 * Return the source referenced by this element, or `null` if this element doe
s not |
| 4534 * reference a Dart library source file. |
| 4535 * |
| 4536 * @return the source for the external Dart library |
| 4537 */ |
| 4538 Source get scriptSource; |
| 4539 } |
| 4540 |
| 4541 /** |
| 4542 * Instances of the class `ExternalHtmlScriptElementImpl` implement an |
| 4543 * [ExternalHtmlScriptElement]. |
| 4544 */ |
| 4545 class ExternalHtmlScriptElementImpl extends HtmlScriptElementImpl implements Ext
ernalHtmlScriptElement { |
| 4546 /** |
| 4547 * The source specified in the `source` attribute or `null` if unspecified. |
| 4548 */ |
| 4549 Source scriptSource; |
| 4550 |
| 4551 /** |
| 4552 * Initialize a newly created script element to have the specified tag name an
d offset. |
| 4553 * |
| 4554 * @param node the XML node from which this element is derived (not `null`) |
| 4555 */ |
| 4556 ExternalHtmlScriptElementImpl(XmlTagNode node) : super(node); |
| 4557 |
| 4558 @override |
| 4559 accept(ElementVisitor visitor) => visitor.visitExternalHtmlScriptElement(this)
; |
| 4560 |
| 4561 @override |
| 4562 ElementKind get kind => ElementKind.EXTERNAL_HTML_SCRIPT; |
| 4563 } |
| 4564 |
| 4565 /** |
| 4566 * The interface `FieldElement` defines the behavior of elements representing a
field defined |
| 4567 * within a type. |
| 4568 */ |
| 4569 abstract class FieldElement implements ClassMemberElement, PropertyInducingEleme
nt { |
| 4570 } |
| 4571 |
| 4572 /** |
| 4573 * Instances of the class `FieldElementImpl` implement a `FieldElement`. |
| 4574 */ |
| 4575 class FieldElementImpl extends PropertyInducingElementImpl implements FieldEleme
nt { |
| 4576 /** |
| 4577 * An empty array of field elements. |
| 4578 */ |
| 4579 static List<FieldElement> EMPTY_ARRAY = new List<FieldElement>(0); |
| 4580 |
| 4581 /** |
| 4582 * Initialize a newly created field element to have the given name. |
| 4583 * |
| 4584 * @param name the name of this element |
| 4585 */ |
| 4586 FieldElementImpl.forNode(Identifier name) : super.forNode(name); |
| 4587 |
| 4588 /** |
| 4589 * Initialize a newly created synthetic field element to have the given name. |
| 4590 * |
| 4591 * @param name the name of this element |
| 4592 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 4593 * declaration of this element |
| 4594 */ |
| 4595 FieldElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 4596 |
| 4597 @override |
| 4598 accept(ElementVisitor visitor) => visitor.visitFieldElement(this); |
| 4599 |
| 4600 @override |
| 4601 ClassElement get enclosingElement => super.enclosingElement as ClassElement; |
| 4602 |
| 4603 @override |
| 4604 ElementKind get kind => ElementKind.FIELD; |
| 4605 |
| 4606 @override |
| 4607 bool get isStatic => hasModifier(Modifier.STATIC); |
| 4608 |
| 4609 /** |
| 4610 * Set whether this field is static to correspond to the given value. |
| 4611 * |
| 4612 * @param isStatic `true` if the field is static |
| 4613 */ |
| 4614 void set static(bool isStatic) { |
| 4615 setModifier(Modifier.STATIC, isStatic); |
| 4616 } |
| 4617 } |
| 4618 |
| 4619 /** |
| 4620 * The interface `FieldFormalParameterElement` defines the behavior of elements
representing a |
| 4621 * field formal parameter defined within a constructor element. |
| 4622 */ |
| 4623 abstract class FieldFormalParameterElement implements ParameterElement { |
| 4624 /** |
| 4625 * Return the field element associated with this field formal parameter, or `n
ull` if the |
| 4626 * parameter references a field that doesn't exist. |
| 4627 * |
| 4628 * @return the field element associated with this field formal parameter |
| 4629 */ |
| 4630 FieldElement get field; |
| 4631 } |
| 4632 |
| 4633 /** |
| 4634 * Instances of the class `FieldFormalParameterElementImpl` extend |
| 4635 * [ParameterElementImpl] to provide the additional information of the [FieldEle
ment] |
| 4636 * associated with the parameter. |
| 4637 */ |
| 4638 class FieldFormalParameterElementImpl extends ParameterElementImpl implements Fi
eldFormalParameterElement { |
| 4639 /** |
| 4640 * The field associated with this field formal parameter. |
| 4641 */ |
| 4642 FieldElement field; |
| 4643 |
| 4644 /** |
| 4645 * Initialize a newly created parameter element to have the given name. |
| 4646 * |
| 4647 * @param name the name of this element |
| 4648 */ |
| 4649 FieldFormalParameterElementImpl(Identifier name) : super.forNode(name); |
| 4650 |
| 4651 @override |
| 4652 accept(ElementVisitor visitor) => visitor.visitFieldFormalParameterElement(thi
s); |
| 4653 |
| 4654 @override |
| 4655 bool get isInitializingFormal => true; |
| 4656 } |
| 4657 |
| 4658 /** |
| 4659 * Instances of the class `FieldFormalParameterMember` represent a parameter ele
ment defined |
| 4660 * in a parameterized type where the values of the type parameters are known. |
| 4661 */ |
| 4662 class FieldFormalParameterMember extends ParameterMember implements FieldFormalP
arameterElement { |
| 4663 /** |
| 4664 * Initialize a newly created element to represent a parameter of the given pa
rameterized type. |
| 4665 * |
| 4666 * @param baseElement the element on which the parameterized element was creat
ed |
| 4667 * @param definingType the type in which the element is defined |
| 4668 */ |
| 4669 FieldFormalParameterMember(FieldFormalParameterElement baseElement, Parameteri
zedType definingType) : super(baseElement, definingType); |
| 4670 |
| 4671 @override |
| 4672 accept(ElementVisitor visitor) => visitor.visitFieldFormalParameterElement(thi
s); |
| 4673 |
| 4674 @override |
| 4675 FieldElement get field => (baseElement as FieldFormalParameterElement).field; |
| 4676 } |
| 4677 |
| 4678 /** |
| 4679 * Instances of the class `FieldMember` represent a field element defined in a p
arameterized |
| 4680 * type where the values of the type parameters are known. |
| 4681 */ |
| 4682 class FieldMember extends VariableMember implements FieldElement { |
| 4683 /** |
| 4684 * If the given field's type is different when any type parameters from the de
fining type's |
| 4685 * declaration are replaced with the actual type arguments from the defining t
ype, create a field |
| 4686 * member representing the given field. Return the member that was created, or
the base field if |
| 4687 * no member was created. |
| 4688 * |
| 4689 * @param baseField the base field for which a member might be created |
| 4690 * @param definingType the type defining the parameters and arguments to be us
ed in the |
| 4691 * substitution |
| 4692 * @return the field element that will return the correctly substituted types |
| 4693 */ |
| 4694 static FieldElement from(FieldElement baseField, InterfaceType definingType) { |
| 4695 if (!_isChangedByTypeSubstitution(baseField, definingType)) { |
| 4696 return baseField; |
| 4697 } |
| 4698 // TODO(brianwilkerson) Consider caching the substituted type in the instanc
e. It would use more |
| 4699 // memory but speed up some operations. We need to see how often the type is
being re-computed. |
| 4700 return new FieldMember(baseField, definingType); |
| 4701 } |
| 4702 |
| 4703 /** |
| 4704 * Determine whether the given field's type is changed when type parameters fr
om the defining |
| 4705 * type's declaration are replaced with the actual type arguments from the def
ining type. |
| 4706 * |
| 4707 * @param baseField the base field |
| 4708 * @param definingType the type defining the parameters and arguments to be us
ed in the |
| 4709 * substitution |
| 4710 * @return true if the type is changed by type substitution. |
| 4711 */ |
| 4712 static bool _isChangedByTypeSubstitution(FieldElement baseField, InterfaceType
definingType) { |
| 4713 List<DartType> argumentTypes = definingType.typeArguments; |
| 4714 if (baseField != null && argumentTypes.length != 0) { |
| 4715 DartType baseType = baseField.type; |
| 4716 List<DartType> parameterTypes = definingType.element.type.typeArguments; |
| 4717 if (baseType != null) { |
| 4718 DartType substitutedType = baseType.substitute2(argumentTypes, parameter
Types); |
| 4719 if (baseType != substitutedType) { |
| 4720 return true; |
| 4721 } |
| 4722 } |
| 4723 // If the field has a propagated type, then we need to check whether the p
ropagated type |
| 4724 // needs substitution. |
| 4725 DartType basePropagatedType = baseField.propagatedType; |
| 4726 if (basePropagatedType != null) { |
| 4727 DartType substitutedPropagatedType = basePropagatedType.substitute2(argu
mentTypes, parameterTypes); |
| 4728 if (basePropagatedType != substitutedPropagatedType) { |
| 4729 return true; |
| 4730 } |
| 4731 } |
| 4732 } |
| 4733 return false; |
| 4734 } |
| 4735 |
| 4736 /** |
| 4737 * Initialize a newly created element to represent a field of the given parame
terized type. |
| 4738 * |
| 4739 * @param baseElement the element on which the parameterized element was creat
ed |
| 4740 * @param definingType the type in which the element is defined |
| 4741 */ |
| 4742 FieldMember(FieldElement baseElement, InterfaceType definingType) : super(base
Element, definingType); |
| 4743 |
| 4744 @override |
| 4745 accept(ElementVisitor visitor) => visitor.visitFieldElement(this); |
| 4746 |
| 4747 @override |
| 4748 FieldElement get baseElement => super.baseElement as FieldElement; |
| 4749 |
| 4750 @override |
| 4751 ClassElement get enclosingElement => baseElement.enclosingElement; |
| 4752 |
| 4753 @override |
| 4754 PropertyAccessorElement get getter => PropertyAccessorMember.from(baseElement.
getter, definingType); |
| 4755 |
| 4756 @override |
| 4757 DartType get propagatedType => substituteFor(baseElement.propagatedType); |
| 4758 |
| 4759 @override |
| 4760 PropertyAccessorElement get setter => PropertyAccessorMember.from(baseElement.
setter, definingType); |
| 4761 |
| 4762 @override |
| 4763 bool get isStatic => baseElement.isStatic; |
| 4764 |
| 4765 @override |
| 4766 String toString() { |
| 4767 JavaStringBuilder builder = new JavaStringBuilder(); |
| 4768 builder.append(type); |
| 4769 builder.append(" "); |
| 4770 builder.append(displayName); |
| 4771 return builder.toString(); |
| 4772 } |
| 4773 |
| 4774 @override |
| 4775 InterfaceType get definingType => super.definingType as InterfaceType; |
| 4776 } |
| 4777 |
| 4778 /** |
| 4779 * The interface `FunctionElement` defines the behavior of elements representing
a function. |
| 4780 */ |
| 4781 abstract class FunctionElement implements ExecutableElement, LocalElement { |
| 4782 /** |
| 4783 * The name of the method that can be implemented by a class to allow its inst
ances to be invoked |
| 4784 * as if they were a function. |
| 4785 */ |
| 4786 static final String CALL_METHOD_NAME = "call"; |
| 4787 |
| 4788 /** |
| 4789 * The name of the method that will be invoked if an attempt is made to invoke
an undefined method |
| 4790 * on an object. |
| 4791 */ |
| 4792 static final String NO_SUCH_METHOD_METHOD_NAME = "noSuchMethod"; |
| 4793 |
| 4794 /** |
| 4795 * The name of the synthetic function defined for libraries that are deferred. |
| 4796 */ |
| 4797 static final String LOAD_LIBRARY_NAME = "loadLibrary"; |
| 4798 |
| 4799 /** |
| 4800 * Return the resolved [FunctionDeclaration] node that declares this [Function
Element] |
| 4801 * . |
| 4802 * |
| 4803 * This method is expensive, because resolved AST might be evicted from cache,
so parsing and |
| 4804 * resolving will be performed. |
| 4805 * |
| 4806 * @return the resolved [FunctionDeclaration], not `null`. |
| 4807 */ |
| 4808 @override |
| 4809 FunctionDeclaration get node; |
| 4810 } |
| 4811 |
| 4812 /** |
| 4813 * Instances of the class `FunctionElementImpl` implement a `FunctionElement`. |
| 4814 */ |
| 4815 class FunctionElementImpl extends ExecutableElementImpl implements FunctionEleme
nt { |
| 4816 /** |
| 4817 * The offset to the beginning of the visible range for this element. |
| 4818 */ |
| 4819 int _visibleRangeOffset = 0; |
| 4820 |
| 4821 /** |
| 4822 * The length of the visible range for this element, or `-1` if this element d
oes not have a |
| 4823 * visible range. |
| 4824 */ |
| 4825 int _visibleRangeLength = -1; |
| 4826 |
| 4827 /** |
| 4828 * An empty array of function elements. |
| 4829 */ |
| 4830 static List<FunctionElement> EMPTY_ARRAY = new List<FunctionElement>(0); |
| 4831 |
| 4832 /** |
| 4833 * Initialize a newly created function element to have the given name. |
| 4834 * |
| 4835 * @param name the name of this element |
| 4836 */ |
| 4837 FunctionElementImpl.forNode(Identifier name) : super.forNode(name); |
| 4838 |
| 4839 /** |
| 4840 * Initialize a newly created function element to have no name and the given o
ffset. This is used |
| 4841 * for function expressions, which have no name. |
| 4842 * |
| 4843 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 4844 * declaration of this element |
| 4845 */ |
| 4846 FunctionElementImpl.forOffset(int nameOffset) : super("", nameOffset); |
| 4847 |
| 4848 /** |
| 4849 * Initialize a newly created function element to have the given name and offs
et. |
| 4850 * |
| 4851 * @param name the name of this element |
| 4852 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 4853 * declaration of this element |
| 4854 */ |
| 4855 FunctionElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 4856 |
| 4857 @override |
| 4858 accept(ElementVisitor visitor) => visitor.visitFunctionElement(this); |
| 4859 |
| 4860 @override |
| 4861 ElementKind get kind => ElementKind.FUNCTION; |
| 4862 |
| 4863 @override |
| 4864 FunctionDeclaration get node => getNodeMatching((node) => node is FunctionDecl
aration); |
| 4865 |
| 4866 @override |
| 4867 SourceRange get visibleRange { |
| 4868 if (_visibleRangeLength < 0) { |
| 4869 return null; |
| 4870 } |
| 4871 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); |
| 4872 } |
| 4873 |
| 4874 @override |
| 4875 bool get isStatic => enclosingElement is CompilationUnitElement; |
| 4876 |
| 4877 /** |
| 4878 * Set the visible range for this element to the range starting at the given o
ffset with the given |
| 4879 * length. |
| 4880 * |
| 4881 * @param offset the offset to the beginning of the visible range for this ele
ment |
| 4882 * @param length the length of the visible range for this element, or `-1` if
this element |
| 4883 * does not have a visible range |
| 4884 */ |
| 4885 void setVisibleRange(int offset, int length) { |
| 4886 _visibleRangeOffset = offset; |
| 4887 _visibleRangeLength = length; |
| 4888 } |
| 4889 |
| 4890 @override |
| 4891 void appendTo(JavaStringBuilder builder) { |
| 4892 String name = displayName; |
| 4893 if (name != null) { |
| 4894 builder.append(name); |
| 4895 } |
| 4896 super.appendTo(builder); |
| 4897 } |
| 4898 |
| 4899 @override |
| 4900 String get identifier { |
| 4901 String identifier = super.identifier; |
| 4902 if (!isStatic) { |
| 4903 identifier += "@${nameOffset}"; |
| 4904 } |
| 4905 return identifier; |
| 4906 } |
| 4907 } |
| 4908 |
| 4909 /** |
| 4910 * The interface `FunctionType` defines the behavior common to objects represent
ing the type |
| 4911 * of a function, method, constructor, getter, or setter. Function types come in
three variations: |
| 4912 * <ol> |
| 4913 * * The types of functions that only have required parameters. These have the g
eneral form |
| 4914 * <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T</i>. |
| 4915 * * The types of functions with optional positional parameters. These have the
general form |
| 4916 * <i>(T<sub>1</sub>, …, T<sub>n</sub>, [T<sub>n+1</sub>, …, T<sub
>n+k</sub>]) → |
| 4917 * T</i>. |
| 4918 * * The types of functions with named parameters. These have the general form <
i>(T<sub>1</sub>, |
| 4919 * …, T<sub>n</sub>, {T<sub>x1</sub> x1, …, T<sub>xk</sub> xk}) &r
arr; T</i>. |
| 4920 * </ol> |
| 4921 */ |
| 4922 abstract class FunctionType implements ParameterizedType { |
| 4923 /** |
| 4924 * Return a map from the names of named parameters to the types of the named p
arameters of this |
| 4925 * type of function. The entries in the map will be iterated in the same order
as the order in |
| 4926 * which the named parameters were defined. If there were no named parameters
declared then the |
| 4927 * map will be empty. |
| 4928 * |
| 4929 * @return a map from the name to the types of the named parameters of this ty
pe of function |
| 4930 */ |
| 4931 Map<String, DartType> get namedParameterTypes; |
| 4932 |
| 4933 /** |
| 4934 * Return an array containing the types of the normal parameters of this type
of function. The |
| 4935 * parameter types are in the same order as they appear in the declaration of
the function. |
| 4936 * |
| 4937 * @return the types of the normal parameters of this type of function |
| 4938 */ |
| 4939 List<DartType> get normalParameterTypes; |
| 4940 |
| 4941 /** |
| 4942 * Return a map from the names of optional (positional) parameters to the type
s of the optional |
| 4943 * parameters of this type of function. The entries in the map will be iterate
d in the same order |
| 4944 * as the order in which the optional parameters were defined. If there were n
o optional |
| 4945 * parameters declared then the map will be empty. |
| 4946 * |
| 4947 * @return a map from the name to the types of the optional parameters of this
type of function |
| 4948 */ |
| 4949 List<DartType> get optionalParameterTypes; |
| 4950 |
| 4951 /** |
| 4952 * Return an array containing the parameters elements of this type of function
. The parameter |
| 4953 * types are in the same order as they appear in the declaration of the functi
on. |
| 4954 * |
| 4955 * @return the parameters elements of this type of function |
| 4956 */ |
| 4957 List<ParameterElement> get parameters; |
| 4958 |
| 4959 /** |
| 4960 * Return the type of object returned by this type of function. |
| 4961 * |
| 4962 * @return the type of object returned by this type of function |
| 4963 */ |
| 4964 DartType get returnType; |
| 4965 |
| 4966 /** |
| 4967 * Return `true` if this type is a subtype of the given type. |
| 4968 * |
| 4969 * A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T</i> is
a subtype of the |
| 4970 * function type <i>(S<sub>1</sub>, …, S<sub>n</sub>) → S</i>, if
all of the following |
| 4971 * conditions are met: |
| 4972 * * Either |
| 4973 * * <i>S</i> is void, or |
| 4974 * * <i>T ⇔ S</i>. |
| 4975 * |
| 4976 * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ S<su
b>i</sub></i>. |
| 4977 * A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>, [T<sub>n+1</sub
>, …, |
| 4978 * T<sub>n+k</sub>]) → T</i> is a subtype of the function type <i>(S<sub>
1</sub>, …, |
| 4979 * S<sub>n</sub>, [S<sub>n+1</sub>, …, S<sub>n+m</sub>]) → S</i>,
if all of the |
| 4980 * following conditions are met: |
| 4981 * * Either |
| 4982 * * <i>S</i> is void, or |
| 4983 * * <i>T ⇔ S</i>. |
| 4984 * |
| 4985 * * <i>k</i> >= <i>m</i> and for all <i>i</i>, 1 <= <i>i</i> <= <i>n+m</i>, <
i>T<sub>i</sub> |
| 4986 * ⇔ S<sub>i</sub></i>. |
| 4987 * A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>, {T<sub>x1</sub>
x1, …, |
| 4988 * T<sub>xk</sub> xk}) → T</i> is a subtype of the function type <i>(S<su
b>1</sub>, …, |
| 4989 * S<sub>n</sub>, {S<sub>y1</sub> y1, …, S<sub>ym</sub> ym}) → S</
i>, if all of the |
| 4990 * following conditions are met: |
| 4991 * * Either |
| 4992 * * <i>S</i> is void, |
| 4993 * * or <i>T ⇔ S</i>. |
| 4994 * |
| 4995 * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ S<su
b>i</sub></i>. |
| 4996 * * <i>k</i> >= <i>m</i> and <i>y<sub>i</sub></i> in <i>{x<sub>1</sub>, &hell
ip;, |
| 4997 * x<sub>k</sub>}</i>, 1 <= <i>i</i> <= <i>m</i>. |
| 4998 * * For all <i>y<sub>i</sub></i> in <i>{y<sub>1</sub>, …, y<sub>m</sub
>}</i>, |
| 4999 * <i>y<sub>i</sub> = x<sub>j</sub> => Tj ⇔ Si</i>. |
| 5000 * In addition, the following subtype rules apply: |
| 5001 * |
| 5002 * <i>(T<sub>1</sub>, …, T<sub>n</sub>, []) → T <: (T<sub>1</sub>,
…, |
| 5003 * T<sub>n</sub>) → T.</i><br> |
| 5004 * <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T <: (T<sub>1</sub>, &he
llip;, |
| 5005 * T<sub>n</sub>, {}) → T.</i><br> |
| 5006 * <i>(T<sub>1</sub>, …, T<sub>n</sub>, {}) → T <: (T<sub>1</sub>,
…, |
| 5007 * T<sub>n</sub>) → T.</i><br> |
| 5008 * <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T <: (T<sub>1</sub>, &he
llip;, |
| 5009 * T<sub>n</sub>, []) → T.</i> |
| 5010 * |
| 5011 * All functions implement the class `Function`. However not all function type
s are a |
| 5012 * subtype of `Function`. If an interface type <i>I</i> includes a method name
d |
| 5013 * `call()`, and the type of `call()` is the function type <i>F</i>, then <i>I
</i> is |
| 5014 * considered to be a subtype of <i>F</i>. |
| 5015 * |
| 5016 * @param type the type being compared with this type |
| 5017 * @return `true` if this type is a subtype of the given type |
| 5018 */ |
| 5019 @override |
| 5020 bool isSubtypeOf(DartType type); |
| 5021 |
| 5022 /** |
| 5023 * Return the type resulting from substituting the given arguments for this ty
pe's parameters. |
| 5024 * This is fully equivalent to `substitute(argumentTypes, getTypeArguments())`
. |
| 5025 * |
| 5026 * @param argumentTypes the actual type arguments being substituted for the ty
pe parameters |
| 5027 * @return the result of performing the substitution |
| 5028 */ |
| 5029 FunctionType substitute3(List<DartType> argumentTypes); |
| 5030 |
| 5031 @override |
| 5032 FunctionType substitute2(List<DartType> argumentTypes, List<DartType> paramete
rTypes); |
| 5033 } |
| 5034 |
| 5035 /** |
| 5036 * The interface `FunctionTypeAliasElement` defines the behavior of elements rep
resenting a |
| 5037 * function type alias (`typedef`). |
| 5038 */ |
| 5039 abstract class FunctionTypeAliasElement implements Element { |
| 5040 /** |
| 5041 * Return the compilation unit in which this type alias is defined. |
| 5042 * |
| 5043 * @return the compilation unit in which this type alias is defined |
| 5044 */ |
| 5045 @override |
| 5046 CompilationUnitElement get enclosingElement; |
| 5047 |
| 5048 /** |
| 5049 * Return the resolved [FunctionTypeAlias] node that declares this |
| 5050 * [FunctionTypeAliasElement] . |
| 5051 * |
| 5052 * This method is expensive, because resolved AST might be evicted from cache,
so parsing and |
| 5053 * resolving will be performed. |
| 5054 * |
| 5055 * @return the resolved [FunctionTypeAlias], not `null`. |
| 5056 */ |
| 5057 @override |
| 5058 FunctionTypeAlias get node; |
| 5059 |
| 5060 /** |
| 5061 * Return an array containing all of the parameters defined by this type alias
. |
| 5062 * |
| 5063 * @return the parameters defined by this type alias |
| 5064 */ |
| 5065 List<ParameterElement> get parameters; |
| 5066 |
| 5067 /** |
| 5068 * Return the return type defined by this type alias. |
| 5069 * |
| 5070 * @return the return type defined by this type alias |
| 5071 */ |
| 5072 DartType get returnType; |
| 5073 |
| 5074 /** |
| 5075 * Return the type of function defined by this type alias. |
| 5076 * |
| 5077 * @return the type of function defined by this type alias |
| 5078 */ |
| 5079 FunctionType get type; |
| 5080 |
| 5081 /** |
| 5082 * Return an array containing all of the type parameters defined for this type
. |
| 5083 * |
| 5084 * @return the type parameters defined for this type |
| 5085 */ |
| 5086 List<TypeParameterElement> get typeParameters; |
| 5087 } |
| 5088 |
| 5089 /** |
| 5090 * Instances of the class `FunctionTypeAliasElementImpl` implement a |
| 5091 * `FunctionTypeAliasElement`. |
| 5092 */ |
| 5093 class FunctionTypeAliasElementImpl extends ElementImpl implements FunctionTypeAl
iasElement { |
| 5094 /** |
| 5095 * An array containing all of the parameters defined by this type alias. |
| 5096 */ |
| 5097 List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY; |
| 5098 |
| 5099 /** |
| 5100 * The return type defined by this type alias. |
| 5101 */ |
| 5102 DartType returnType; |
| 5103 |
| 5104 /** |
| 5105 * The type of function defined by this type alias. |
| 5106 */ |
| 5107 FunctionType type; |
| 5108 |
| 5109 /** |
| 5110 * An array containing all of the type parameters defined for this type. |
| 5111 */ |
| 5112 List<TypeParameterElement> _typeParameters = TypeParameterElementImpl.EMPTY_AR
RAY; |
| 5113 |
| 5114 /** |
| 5115 * An empty array of type alias elements. |
| 5116 */ |
| 5117 static List<FunctionTypeAliasElement> EMPTY_ARRAY = new List<FunctionTypeAlias
Element>(0); |
| 5118 |
| 5119 /** |
| 5120 * Initialize a newly created type alias element to have the given name. |
| 5121 * |
| 5122 * @param name the name of this element |
| 5123 */ |
| 5124 FunctionTypeAliasElementImpl(Identifier name) : super.forNode(name); |
| 5125 |
| 5126 @override |
| 5127 accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this); |
| 5128 |
| 5129 @override |
| 5130 ElementImpl getChild(String identifier) { |
| 5131 for (VariableElement parameter in _parameters) { |
| 5132 if ((parameter as VariableElementImpl).identifier == identifier) { |
| 5133 return parameter as VariableElementImpl; |
| 5134 } |
| 5135 } |
| 5136 for (TypeParameterElement typeParameter in _typeParameters) { |
| 5137 if ((typeParameter as TypeParameterElementImpl).identifier == identifier)
{ |
| 5138 return typeParameter as TypeParameterElementImpl; |
| 5139 } |
| 5140 } |
| 5141 return null; |
| 5142 } |
| 5143 |
| 5144 @override |
| 5145 CompilationUnitElement get enclosingElement => super.enclosingElement as Compi
lationUnitElement; |
| 5146 |
| 5147 @override |
| 5148 ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS; |
| 5149 |
| 5150 @override |
| 5151 FunctionTypeAlias get node => getNodeMatching((node) => node is FunctionTypeAl
ias); |
| 5152 |
| 5153 @override |
| 5154 List<ParameterElement> get parameters => _parameters; |
| 5155 |
| 5156 @override |
| 5157 List<TypeParameterElement> get typeParameters => _typeParameters; |
| 5158 |
| 5159 /** |
| 5160 * Set the parameters defined by this type alias to the given parameters. |
| 5161 * |
| 5162 * @param parameters the parameters defined by this type alias |
| 5163 */ |
| 5164 void set parameters(List<ParameterElement> parameters) { |
| 5165 if (parameters != null) { |
| 5166 for (ParameterElement parameter in parameters) { |
| 5167 (parameter as ParameterElementImpl).enclosingElement = this; |
| 5168 } |
| 5169 } |
| 5170 this._parameters = parameters; |
| 5171 } |
| 5172 |
| 5173 /** |
| 5174 * Set the type parameters defined for this type to the given parameters. |
| 5175 * |
| 5176 * @param typeParameters the type parameters defined for this type |
| 5177 */ |
| 5178 void set typeParameters(List<TypeParameterElement> typeParameters) { |
| 5179 for (TypeParameterElement typeParameter in typeParameters) { |
| 5180 (typeParameter as TypeParameterElementImpl).enclosingElement = this; |
| 5181 } |
| 5182 this._typeParameters = typeParameters; |
| 5183 } |
| 5184 |
| 5185 /** |
| 5186 * Set the parameters defined by this type alias to the given parameters witho
ut becoming the |
| 5187 * parent of the parameters. This should only be used by the [TypeResolverVisi
tor] when |
| 5188 * creating a synthetic type alias. |
| 5189 * |
| 5190 * @param parameters the parameters defined by this type alias |
| 5191 */ |
| 5192 void shareParameters(List<ParameterElement> parameters) { |
| 5193 this._parameters = parameters; |
| 5194 } |
| 5195 |
| 5196 /** |
| 5197 * Set the type parameters defined for this type to the given parameters witho
ut becoming the |
| 5198 * parent of the parameters. This should only be used by the [TypeResolverVisi
tor] when |
| 5199 * creating a synthetic type alias. |
| 5200 * |
| 5201 * @param typeParameters the type parameters defined for this type |
| 5202 */ |
| 5203 void shareTypeParameters(List<TypeParameterElement> typeParameters) { |
| 5204 this._typeParameters = typeParameters; |
| 5205 } |
| 5206 |
| 5207 @override |
| 5208 void visitChildren(ElementVisitor visitor) { |
| 5209 super.visitChildren(visitor); |
| 5210 safelyVisitChildren(_parameters, visitor); |
| 5211 safelyVisitChildren(_typeParameters, visitor); |
| 5212 } |
| 5213 |
| 5214 @override |
| 5215 void appendTo(JavaStringBuilder builder) { |
| 5216 builder.append("typedef "); |
| 5217 builder.append(displayName); |
| 5218 int typeParameterCount = _typeParameters.length; |
| 5219 if (typeParameterCount > 0) { |
| 5220 builder.append("<"); |
| 5221 for (int i = 0; i < typeParameterCount; i++) { |
| 5222 if (i > 0) { |
| 5223 builder.append(", "); |
| 5224 } |
| 5225 (_typeParameters[i] as TypeParameterElementImpl).appendTo(builder); |
| 5226 } |
| 5227 builder.append(">"); |
| 5228 } |
| 5229 builder.append("("); |
| 5230 int parameterCount = _parameters.length; |
| 5231 for (int i = 0; i < parameterCount; i++) { |
| 5232 if (i > 0) { |
| 5233 builder.append(", "); |
| 5234 } |
| 5235 (_parameters[i] as ParameterElementImpl).appendTo(builder); |
| 5236 } |
| 5237 builder.append(")"); |
| 5238 if (type != null) { |
| 5239 builder.append(Element.RIGHT_ARROW); |
| 5240 builder.append(type.returnType); |
| 5241 } |
| 5242 } |
| 5243 } |
| 5244 |
| 5245 /** |
| 5246 * Instances of the class `FunctionTypeImpl` defines the behavior common to obje
cts |
| 5247 * representing the type of a function, method, constructor, getter, or setter. |
| 5248 */ |
| 5249 class FunctionTypeImpl extends TypeImpl implements FunctionType { |
| 5250 /** |
| 5251 * Return `true` if all of the name/type pairs in the first map are equal to t
he |
| 5252 * corresponding name/type pairs in the second map. The maps are expected to i
terate over their |
| 5253 * entries in the same order in which those entries were added to the map. |
| 5254 * |
| 5255 * @param firstTypes the first map of name/type pairs being compared |
| 5256 * @param secondTypes the second map of name/type pairs being compared |
| 5257 * @param visitedElementPairs a set of visited element pairs |
| 5258 * @return `true` if all of the name/type pairs in the first map are equal to
the |
| 5259 * corresponding name/type pairs in the second map |
| 5260 */ |
| 5261 static bool _equals(Map<String, DartType> firstTypes, Map<String, DartType> se
condTypes, Set<ElementPair> visitedElementPairs) { |
| 5262 if (secondTypes.length != firstTypes.length) { |
| 5263 return false; |
| 5264 } |
| 5265 JavaIterator<MapEntry<String, DartType>> firstIterator = new JavaIterator(ge
tMapEntrySet(firstTypes)); |
| 5266 JavaIterator<MapEntry<String, DartType>> secondIterator = new JavaIterator(g
etMapEntrySet(secondTypes)); |
| 5267 while (firstIterator.hasNext) { |
| 5268 MapEntry<String, DartType> firstEntry = firstIterator.next(); |
| 5269 MapEntry<String, DartType> secondEntry = secondIterator.next(); |
| 5270 if (firstEntry.getKey() != secondEntry.getKey() || !(firstEntry.getValue()
as TypeImpl).internalEquals(secondEntry.getValue(), visitedElementPairs)) { |
| 5271 return false; |
| 5272 } |
| 5273 } |
| 5274 return true; |
| 5275 } |
| 5276 |
| 5277 /** |
| 5278 * An array containing the actual types of the type arguments. |
| 5279 */ |
| 5280 List<DartType> typeArguments = TypeImpl.EMPTY_ARRAY; |
| 5281 |
| 5282 /** |
| 5283 * Initialize a newly created function type to be declared by the given elemen
t and to have the |
| 5284 * given name. |
| 5285 * |
| 5286 * @param element the element representing the declaration of the function typ
e |
| 5287 */ |
| 5288 FunctionTypeImpl.con1(ExecutableElement element) : super(element, element == n
ull ? null : element.name); |
| 5289 |
| 5290 /** |
| 5291 * Initialize a newly created function type to be declared by the given elemen
t and to have the |
| 5292 * given name. |
| 5293 * |
| 5294 * @param element the element representing the declaration of the function typ
e |
| 5295 */ |
| 5296 FunctionTypeImpl.con2(FunctionTypeAliasElement element) : super(element, eleme
nt == null ? null : element.name); |
| 5297 |
| 5298 @override |
| 5299 bool operator ==(Object object) => internalEquals(object, new HashSet<ElementP
air>()); |
| 5300 |
| 5301 @override |
| 5302 String get displayName { |
| 5303 String name = this.name; |
| 5304 if (name == null || name.length == 0) { |
| 5305 // Function types have an empty name when they are defined implicitly by e
ither a closure or |
| 5306 // as part of a parameter declaration. |
| 5307 List<DartType> normalParameterTypes = this.normalParameterTypes; |
| 5308 List<DartType> optionalParameterTypes = this.optionalParameterTypes; |
| 5309 Map<String, DartType> namedParameterTypes = this.namedParameterTypes; |
| 5310 DartType returnType = this.returnType; |
| 5311 JavaStringBuilder builder = new JavaStringBuilder(); |
| 5312 builder.append("("); |
| 5313 bool needsComma = false; |
| 5314 if (normalParameterTypes.length > 0) { |
| 5315 for (DartType type in normalParameterTypes) { |
| 5316 if (needsComma) { |
| 5317 builder.append(", "); |
| 5318 } else { |
| 5319 needsComma = true; |
| 5320 } |
| 5321 builder.append(type.displayName); |
| 5322 } |
| 5323 } |
| 5324 if (optionalParameterTypes.length > 0) { |
| 5325 if (needsComma) { |
| 5326 builder.append(", "); |
| 5327 needsComma = false; |
| 5328 } |
| 5329 builder.append("["); |
| 5330 for (DartType type in optionalParameterTypes) { |
| 5331 if (needsComma) { |
| 5332 builder.append(", "); |
| 5333 } else { |
| 5334 needsComma = true; |
| 5335 } |
| 5336 builder.append(type.displayName); |
| 5337 } |
| 5338 builder.append("]"); |
| 5339 needsComma = true; |
| 5340 } |
| 5341 if (namedParameterTypes.length > 0) { |
| 5342 if (needsComma) { |
| 5343 builder.append(", "); |
| 5344 needsComma = false; |
| 5345 } |
| 5346 builder.append("{"); |
| 5347 for (MapEntry<String, DartType> entry in getMapEntrySet(namedParameterTy
pes)) { |
| 5348 if (needsComma) { |
| 5349 builder.append(", "); |
| 5350 } else { |
| 5351 needsComma = true; |
| 5352 } |
| 5353 builder.append(entry.getKey()); |
| 5354 builder.append(": "); |
| 5355 builder.append(entry.getValue().displayName); |
| 5356 } |
| 5357 builder.append("}"); |
| 5358 needsComma = true; |
| 5359 } |
| 5360 builder.append(")"); |
| 5361 builder.append(Element.RIGHT_ARROW); |
| 5362 if (returnType == null) { |
| 5363 builder.append("null"); |
| 5364 } else { |
| 5365 builder.append(returnType.displayName); |
| 5366 } |
| 5367 name = builder.toString(); |
| 5368 } |
| 5369 return name; |
| 5370 } |
| 5371 |
| 5372 @override |
| 5373 Map<String, DartType> get namedParameterTypes { |
| 5374 LinkedHashMap<String, DartType> namedParameterTypes = new LinkedHashMap<Stri
ng, DartType>(); |
| 5375 List<ParameterElement> parameters = baseParameters; |
| 5376 if (parameters.length == 0) { |
| 5377 return namedParameterTypes; |
| 5378 } |
| 5379 List<DartType> typeParameters = TypeParameterTypeImpl.getTypes(this.typePara
meters); |
| 5380 for (ParameterElement parameter in parameters) { |
| 5381 if (parameter.parameterKind == ParameterKind.NAMED) { |
| 5382 DartType type = parameter.type; |
| 5383 if (typeArguments.length != 0 && typeArguments.length == typeParameters.
length) { |
| 5384 type = type.substitute2(typeArguments, typeParameters); |
| 5385 } |
| 5386 namedParameterTypes[parameter.name] = type; |
| 5387 } |
| 5388 } |
| 5389 return namedParameterTypes; |
| 5390 } |
| 5391 |
| 5392 @override |
| 5393 List<DartType> get normalParameterTypes { |
| 5394 List<ParameterElement> parameters = baseParameters; |
| 5395 if (parameters.length == 0) { |
| 5396 return TypeImpl.EMPTY_ARRAY; |
| 5397 } |
| 5398 List<DartType> typeParameters = TypeParameterTypeImpl.getTypes(this.typePara
meters); |
| 5399 List<DartType> types = new List<DartType>(); |
| 5400 for (ParameterElement parameter in parameters) { |
| 5401 if (parameter.parameterKind == ParameterKind.REQUIRED) { |
| 5402 DartType type = parameter.type; |
| 5403 if (typeArguments.length != 0 && typeArguments.length == typeParameters.
length) { |
| 5404 type = type.substitute2(typeArguments, typeParameters); |
| 5405 } |
| 5406 types.add(type); |
| 5407 } |
| 5408 } |
| 5409 return new List.from(types); |
| 5410 } |
| 5411 |
| 5412 @override |
| 5413 List<DartType> get optionalParameterTypes { |
| 5414 List<ParameterElement> parameters = baseParameters; |
| 5415 if (parameters.length == 0) { |
| 5416 return TypeImpl.EMPTY_ARRAY; |
| 5417 } |
| 5418 List<DartType> typeParameters = TypeParameterTypeImpl.getTypes(this.typePara
meters); |
| 5419 List<DartType> types = new List<DartType>(); |
| 5420 for (ParameterElement parameter in parameters) { |
| 5421 if (parameter.parameterKind == ParameterKind.POSITIONAL) { |
| 5422 DartType type = parameter.type; |
| 5423 if (typeArguments.length != 0 && typeArguments.length == typeParameters.
length) { |
| 5424 type = type.substitute2(typeArguments, typeParameters); |
| 5425 } |
| 5426 types.add(type); |
| 5427 } |
| 5428 } |
| 5429 return new List.from(types); |
| 5430 } |
| 5431 |
| 5432 @override |
| 5433 List<ParameterElement> get parameters { |
| 5434 List<ParameterElement> baseParameters = this.baseParameters; |
| 5435 // no parameters, quick return |
| 5436 int parameterCount = baseParameters.length; |
| 5437 if (parameterCount == 0) { |
| 5438 return baseParameters; |
| 5439 } |
| 5440 // create specialized parameters |
| 5441 List<ParameterElement> specializedParameters = new List<ParameterElement>(pa
rameterCount); |
| 5442 for (int i = 0; i < parameterCount; i++) { |
| 5443 specializedParameters[i] = ParameterMember.from(baseParameters[i], this); |
| 5444 } |
| 5445 return specializedParameters; |
| 5446 } |
| 5447 |
| 5448 @override |
| 5449 DartType get returnType { |
| 5450 DartType baseReturnType = this.baseReturnType; |
| 5451 if (baseReturnType == null) { |
| 5452 // TODO(brianwilkerson) This is a patch. The return type should never be n
ull and we need to |
| 5453 // understand why it is and fix it. |
| 5454 return DynamicTypeImpl.instance; |
| 5455 } |
| 5456 // If there are no arguments to substitute, or if the arguments size doesn't
match the parameter |
| 5457 // size, return the base return type. |
| 5458 if (typeArguments.length == 0 || typeArguments.length != typeParameters.leng
th) { |
| 5459 return baseReturnType; |
| 5460 } |
| 5461 return baseReturnType.substitute2(typeArguments, TypeParameterTypeImpl.getTy
pes(typeParameters)); |
| 5462 } |
| 5463 |
| 5464 @override |
| 5465 List<TypeParameterElement> get typeParameters { |
| 5466 Element element = this.element; |
| 5467 if (element is FunctionTypeAliasElement) { |
| 5468 return element.typeParameters; |
| 5469 } |
| 5470 ClassElement definingClass = element.getAncestor((element) => element is Cla
ssElement); |
| 5471 if (definingClass != null) { |
| 5472 return definingClass.typeParameters; |
| 5473 } |
| 5474 return TypeParameterElementImpl.EMPTY_ARRAY; |
| 5475 } |
| 5476 |
| 5477 @override |
| 5478 int get hashCode { |
| 5479 if (element == null) { |
| 5480 return 0; |
| 5481 } |
| 5482 // Reference the arrays of parameters |
| 5483 List<DartType> normalParameterTypes = this.normalParameterTypes; |
| 5484 List<DartType> optionalParameterTypes = this.optionalParameterTypes; |
| 5485 Iterable<DartType> namedParameterTypes = this.namedParameterTypes.values; |
| 5486 // Generate the hashCode |
| 5487 int hashCode = returnType.hashCode; |
| 5488 for (int i = 0; i < normalParameterTypes.length; i++) { |
| 5489 hashCode = (hashCode << 1) + normalParameterTypes[i].hashCode; |
| 5490 } |
| 5491 for (int i = 0; i < optionalParameterTypes.length; i++) { |
| 5492 hashCode = (hashCode << 1) + optionalParameterTypes[i].hashCode; |
| 5493 } |
| 5494 for (DartType type in namedParameterTypes) { |
| 5495 hashCode = (hashCode << 1) + type.hashCode; |
| 5496 } |
| 5497 return hashCode; |
| 5498 } |
| 5499 |
| 5500 @override |
| 5501 bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_
TypePair> visitedTypePairs) { |
| 5502 // trivial base cases |
| 5503 if (type == null) { |
| 5504 return false; |
| 5505 } else if (identical(this, type) || type.isDynamic || type.isDartCoreFunctio
n || type.isObject) { |
| 5506 return true; |
| 5507 } else if (type is UnionType) { |
| 5508 return (type as UnionTypeImpl).internalUnionTypeIsMoreSpecificThan(this, w
ithDynamic, visitedTypePairs); |
| 5509 } else if (type is! FunctionType) { |
| 5510 return false; |
| 5511 } else if (this == type) { |
| 5512 return true; |
| 5513 } |
| 5514 FunctionType t = this; |
| 5515 FunctionType s = type as FunctionType; |
| 5516 List<DartType> tTypes = t.normalParameterTypes; |
| 5517 List<DartType> tOpTypes = t.optionalParameterTypes; |
| 5518 List<DartType> sTypes = s.normalParameterTypes; |
| 5519 List<DartType> sOpTypes = s.optionalParameterTypes; |
| 5520 // If one function has positional and the other has named parameters, return
false. |
| 5521 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || (tOpTypes.l
ength > 0 && s.namedParameterTypes.length > 0)) { |
| 5522 return false; |
| 5523 } |
| 5524 // named parameters case |
| 5525 if (t.namedParameterTypes.length > 0) { |
| 5526 // check that the number of required parameters are equal, and check that
every t_i is |
| 5527 // more specific than every s_i |
| 5528 if (t.normalParameterTypes.length != s.normalParameterTypes.length) { |
| 5529 return false; |
| 5530 } else if (t.normalParameterTypes.length > 0) { |
| 5531 for (int i = 0; i < tTypes.length; i++) { |
| 5532 if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2(sTypes[i], withDynami
c, visitedTypePairs)) { |
| 5533 return false; |
| 5534 } |
| 5535 } |
| 5536 } |
| 5537 Map<String, DartType> namedTypesT = t.namedParameterTypes; |
| 5538 Map<String, DartType> namedTypesS = s.namedParameterTypes; |
| 5539 // if k >= m is false, return false: the passed function type has more nam
ed parameter types than this |
| 5540 if (namedTypesT.length < namedTypesS.length) { |
| 5541 return false; |
| 5542 } |
| 5543 // Loop through each element in S verifying that T has a matching paramete
r name and that the |
| 5544 // corresponding type is more specific then the type in S. |
| 5545 JavaIterator<MapEntry<String, DartType>> iteratorS = new JavaIterator(getM
apEntrySet(namedTypesS)); |
| 5546 while (iteratorS.hasNext) { |
| 5547 MapEntry<String, DartType> entryS = iteratorS.next(); |
| 5548 DartType typeT = namedTypesT[entryS.getKey()]; |
| 5549 if (typeT == null) { |
| 5550 return false; |
| 5551 } |
| 5552 if (!(typeT as TypeImpl).isMoreSpecificThan2(entryS.getValue(), withDyna
mic, visitedTypePairs)) { |
| 5553 return false; |
| 5554 } |
| 5555 } |
| 5556 } else if (s.namedParameterTypes.length > 0) { |
| 5557 return false; |
| 5558 } else { |
| 5559 // positional parameter case |
| 5560 int tArgLength = tTypes.length + tOpTypes.length; |
| 5561 int sArgLength = sTypes.length + sOpTypes.length; |
| 5562 // Check that the total number of parameters in t is greater than or equal
to the number of |
| 5563 // parameters in s and that the number of required parameters in s is grea
ter than or equal to |
| 5564 // the number of required parameters in t. |
| 5565 if (tArgLength < sArgLength || sTypes.length < tTypes.length) { |
| 5566 return false; |
| 5567 } |
| 5568 if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
| 5569 // No positional arguments, don't copy contents to new array |
| 5570 for (int i = 0; i < sTypes.length; i++) { |
| 5571 if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2(sTypes[i], withDynami
c, visitedTypePairs)) { |
| 5572 return false; |
| 5573 } |
| 5574 } |
| 5575 } else { |
| 5576 // Else, we do have positional parameters, copy required and positional
parameter types into |
| 5577 // arrays to do the compare (for loop below). |
| 5578 List<DartType> tAllTypes = new List<DartType>(sArgLength); |
| 5579 for (int i = 0; i < tTypes.length; i++) { |
| 5580 tAllTypes[i] = tTypes[i]; |
| 5581 } |
| 5582 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { |
| 5583 tAllTypes[i] = tOpTypes[j]; |
| 5584 } |
| 5585 List<DartType> sAllTypes = new List<DartType>(sArgLength); |
| 5586 for (int i = 0; i < sTypes.length; i++) { |
| 5587 sAllTypes[i] = sTypes[i]; |
| 5588 } |
| 5589 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { |
| 5590 sAllTypes[i] = sOpTypes[j]; |
| 5591 } |
| 5592 for (int i = 0; i < sAllTypes.length; i++) { |
| 5593 if (!(tAllTypes[i] as TypeImpl).isMoreSpecificThan2(sAllTypes[i], with
Dynamic, visitedTypePairs)) { |
| 5594 return false; |
| 5595 } |
| 5596 } |
| 5597 } |
| 5598 } |
| 5599 DartType tRetType = t.returnType; |
| 5600 DartType sRetType = s.returnType; |
| 5601 return sRetType.isVoid || (tRetType as TypeImpl).isMoreSpecificThan2(sRetTyp
e, withDynamic, visitedTypePairs); |
| 5602 } |
| 5603 |
| 5604 /** |
| 5605 * Return `true` if this type is assignable to the given type. A function type
<i>T</i> may |
| 5606 * be assigned to a function type <i>S</i>, written <i>T</i> ⇔ <i>S</i>,
iff <i>T</i> <: |
| 5607 * <i>S</i> (Function Types section of spec). Note that this is more restricti
ve than the |
| 5608 * "may be assigned to" rule for interface types. |
| 5609 * |
| 5610 * |
| 5611 * @param type the type being compared with this type |
| 5612 * @return `true` if this type is assignable to the given type |
| 5613 */ |
| 5614 @override |
| 5615 bool isAssignableTo(DartType type) => isSubtypeOf2(type, new HashSet<TypeImpl_
TypePair>()); |
| 5616 |
| 5617 @override |
| 5618 FunctionTypeImpl substitute3(List<DartType> argumentTypes) => substitute2(argu
mentTypes, typeArguments); |
| 5619 |
| 5620 @override |
| 5621 FunctionTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> para
meterTypes) { |
| 5622 if (argumentTypes.length != parameterTypes.length) { |
| 5623 throw new IllegalArgumentException("argumentTypes.length (${argumentTypes.
length}) != parameterTypes.length (${parameterTypes.length})"); |
| 5624 } |
| 5625 if (argumentTypes.length == 0) { |
| 5626 return this; |
| 5627 } |
| 5628 Element element = this.element; |
| 5629 FunctionTypeImpl newType = (element is ExecutableElement) ? new FunctionType
Impl.con1(element) : new FunctionTypeImpl.con2(element as FunctionTypeAliasEleme
nt); |
| 5630 newType.typeArguments = TypeImpl.substitute(typeArguments, argumentTypes, pa
rameterTypes); |
| 5631 return newType; |
| 5632 } |
| 5633 |
| 5634 @override |
| 5635 void appendTo(JavaStringBuilder builder) { |
| 5636 List<DartType> normalParameterTypes = this.normalParameterTypes; |
| 5637 List<DartType> optionalParameterTypes = this.optionalParameterTypes; |
| 5638 Map<String, DartType> namedParameterTypes = this.namedParameterTypes; |
| 5639 DartType returnType = this.returnType; |
| 5640 builder.append("("); |
| 5641 bool needsComma = false; |
| 5642 if (normalParameterTypes.length > 0) { |
| 5643 for (DartType type in normalParameterTypes) { |
| 5644 if (needsComma) { |
| 5645 builder.append(", "); |
| 5646 } else { |
| 5647 needsComma = true; |
| 5648 } |
| 5649 (type as TypeImpl).appendTo(builder); |
| 5650 } |
| 5651 } |
| 5652 if (optionalParameterTypes.length > 0) { |
| 5653 if (needsComma) { |
| 5654 builder.append(", "); |
| 5655 needsComma = false; |
| 5656 } |
| 5657 builder.append("["); |
| 5658 for (DartType type in optionalParameterTypes) { |
| 5659 if (needsComma) { |
| 5660 builder.append(", "); |
| 5661 } else { |
| 5662 needsComma = true; |
| 5663 } |
| 5664 (type as TypeImpl).appendTo(builder); |
| 5665 } |
| 5666 builder.append("]"); |
| 5667 needsComma = true; |
| 5668 } |
| 5669 if (namedParameterTypes.length > 0) { |
| 5670 if (needsComma) { |
| 5671 builder.append(", "); |
| 5672 needsComma = false; |
| 5673 } |
| 5674 builder.append("{"); |
| 5675 for (MapEntry<String, DartType> entry in getMapEntrySet(namedParameterType
s)) { |
| 5676 if (needsComma) { |
| 5677 builder.append(", "); |
| 5678 } else { |
| 5679 needsComma = true; |
| 5680 } |
| 5681 builder.append(entry.getKey()); |
| 5682 builder.append(": "); |
| 5683 (entry.getValue() as TypeImpl).appendTo(builder); |
| 5684 } |
| 5685 builder.append("}"); |
| 5686 needsComma = true; |
| 5687 } |
| 5688 builder.append(")"); |
| 5689 builder.append(Element.RIGHT_ARROW); |
| 5690 if (returnType == null) { |
| 5691 builder.append("null"); |
| 5692 } else { |
| 5693 (returnType as TypeImpl).appendTo(builder); |
| 5694 } |
| 5695 } |
| 5696 |
| 5697 /** |
| 5698 * @return the base parameter elements of this function element, not `null`. |
| 5699 */ |
| 5700 List<ParameterElement> get baseParameters { |
| 5701 Element element = this.element; |
| 5702 if (element is ExecutableElement) { |
| 5703 return element.parameters; |
| 5704 } else { |
| 5705 return (element as FunctionTypeAliasElement).parameters; |
| 5706 } |
| 5707 } |
| 5708 |
| 5709 @override |
| 5710 bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) { |
| 5711 if (object is! FunctionTypeImpl) { |
| 5712 return false; |
| 5713 } |
| 5714 FunctionTypeImpl otherType = object as FunctionTypeImpl; |
| 5715 // If the visitedTypePairs already has the pair (this, type), use the elemen
ts to determine equality |
| 5716 ElementPair elementPair = new ElementPair(element, otherType.element); |
| 5717 if (!visitedElementPairs.add(elementPair)) { |
| 5718 return elementPair.firstElt == elementPair.secondElt; |
| 5719 } |
| 5720 // Compute the result |
| 5721 bool result = TypeImpl.equalArrays(normalParameterTypes, otherType.normalPar
ameterTypes, visitedElementPairs) && TypeImpl.equalArrays(optionalParameterTypes
, otherType.optionalParameterTypes, visitedElementPairs) && _equals(namedParamet
erTypes, otherType.namedParameterTypes, visitedElementPairs) && (returnType as T
ypeImpl).internalEquals(otherType.returnType, visitedElementPairs); |
| 5722 // Remove the pair from our visited pairs list |
| 5723 visitedElementPairs.remove(elementPair); |
| 5724 // Return the result |
| 5725 return result; |
| 5726 } |
| 5727 |
| 5728 @override |
| 5729 bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePair
s) { |
| 5730 // trivial base cases |
| 5731 if (type == null) { |
| 5732 return false; |
| 5733 } else if (identical(this, type) || type.isDynamic || type.isDartCoreFunctio
n || type.isObject) { |
| 5734 return true; |
| 5735 } else if (type is UnionType) { |
| 5736 return (type as UnionTypeImpl).internalUnionTypeIsSuperTypeOf(this, visite
dTypePairs); |
| 5737 } else if (type is! FunctionType) { |
| 5738 return false; |
| 5739 } else if (this == type) { |
| 5740 return true; |
| 5741 } |
| 5742 FunctionType t = this; |
| 5743 FunctionType s = type as FunctionType; |
| 5744 List<DartType> tTypes = t.normalParameterTypes; |
| 5745 List<DartType> tOpTypes = t.optionalParameterTypes; |
| 5746 List<DartType> sTypes = s.normalParameterTypes; |
| 5747 List<DartType> sOpTypes = s.optionalParameterTypes; |
| 5748 // If one function has positional and the other has named parameters, return
false. |
| 5749 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || (tOpTypes.l
ength > 0 && s.namedParameterTypes.length > 0)) { |
| 5750 return false; |
| 5751 } |
| 5752 // named parameters case |
| 5753 if (t.namedParameterTypes.length > 0) { |
| 5754 // check that the number of required parameters are equal, and check that
every t_i is |
| 5755 // assignable to every s_i |
| 5756 if (t.normalParameterTypes.length != s.normalParameterTypes.length) { |
| 5757 return false; |
| 5758 } else if (t.normalParameterTypes.length > 0) { |
| 5759 for (int i = 0; i < tTypes.length; i++) { |
| 5760 if (!(tTypes[i] as TypeImpl).isAssignableTo2(sTypes[i], visitedTypePai
rs)) { |
| 5761 return false; |
| 5762 } |
| 5763 } |
| 5764 } |
| 5765 Map<String, DartType> namedTypesT = t.namedParameterTypes; |
| 5766 Map<String, DartType> namedTypesS = s.namedParameterTypes; |
| 5767 // if k >= m is false, return false: the passed function type has more nam
ed parameter types than this |
| 5768 if (namedTypesT.length < namedTypesS.length) { |
| 5769 return false; |
| 5770 } |
| 5771 // Loop through each element in S verifying that T has a matching paramete
r name and that the |
| 5772 // corresponding type is assignable to the type in S. |
| 5773 JavaIterator<MapEntry<String, DartType>> iteratorS = new JavaIterator(getM
apEntrySet(namedTypesS)); |
| 5774 while (iteratorS.hasNext) { |
| 5775 MapEntry<String, DartType> entryS = iteratorS.next(); |
| 5776 DartType typeT = namedTypesT[entryS.getKey()]; |
| 5777 if (typeT == null) { |
| 5778 return false; |
| 5779 } |
| 5780 if (!(typeT as TypeImpl).isAssignableTo2(entryS.getValue(), visitedTypeP
airs)) { |
| 5781 return false; |
| 5782 } |
| 5783 } |
| 5784 } else if (s.namedParameterTypes.length > 0) { |
| 5785 return false; |
| 5786 } else { |
| 5787 // positional parameter case |
| 5788 int tArgLength = tTypes.length + tOpTypes.length; |
| 5789 int sArgLength = sTypes.length + sOpTypes.length; |
| 5790 // Check that the total number of parameters in t is greater than or equal
to the number of |
| 5791 // parameters in s and that the number of required parameters in s is grea
ter than or equal to |
| 5792 // the number of required parameters in t. |
| 5793 if (tArgLength < sArgLength || sTypes.length < tTypes.length) { |
| 5794 return false; |
| 5795 } |
| 5796 if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
| 5797 // No positional arguments, don't copy contents to new array |
| 5798 for (int i = 0; i < sTypes.length; i++) { |
| 5799 if (!(tTypes[i] as TypeImpl).isAssignableTo2(sTypes[i], visitedTypePai
rs)) { |
| 5800 return false; |
| 5801 } |
| 5802 } |
| 5803 } else { |
| 5804 // Else, we do have positional parameters, copy required and positional
parameter types into |
| 5805 // arrays to do the compare (for loop below). |
| 5806 List<DartType> tAllTypes = new List<DartType>(sArgLength); |
| 5807 for (int i = 0; i < tTypes.length; i++) { |
| 5808 tAllTypes[i] = tTypes[i]; |
| 5809 } |
| 5810 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { |
| 5811 tAllTypes[i] = tOpTypes[j]; |
| 5812 } |
| 5813 List<DartType> sAllTypes = new List<DartType>(sArgLength); |
| 5814 for (int i = 0; i < sTypes.length; i++) { |
| 5815 sAllTypes[i] = sTypes[i]; |
| 5816 } |
| 5817 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { |
| 5818 sAllTypes[i] = sOpTypes[j]; |
| 5819 } |
| 5820 for (int i = 0; i < sAllTypes.length; i++) { |
| 5821 if (!(tAllTypes[i] as TypeImpl).isAssignableTo2(sAllTypes[i], visitedT
ypePairs)) { |
| 5822 return false; |
| 5823 } |
| 5824 } |
| 5825 } |
| 5826 } |
| 5827 DartType tRetType = t.returnType; |
| 5828 DartType sRetType = s.returnType; |
| 5829 return sRetType.isVoid || (tRetType as TypeImpl).isAssignableTo2(sRetType, v
isitedTypePairs); |
| 5830 } |
| 5831 |
| 5832 /** |
| 5833 * Return the return type defined by this function's element. |
| 5834 * |
| 5835 * @return the return type defined by this function's element |
| 5836 */ |
| 5837 DartType get baseReturnType { |
| 5838 Element element = this.element; |
| 5839 if (element is ExecutableElement) { |
| 5840 return element.returnType; |
| 5841 } else { |
| 5842 return (element as FunctionTypeAliasElement).returnType; |
| 5843 } |
| 5844 } |
| 5845 } |
| 5846 |
| 5847 /** |
| 5848 * Instances of the class `GeneralizingElementVisitor` implement an element visi
tor that will |
| 5849 * recursively visit all of the elements in an element model (like instances of
the class |
| 5850 * [RecursiveElementVisitor]). In addition, when an element of a specific type i
s visited not |
| 5851 * only will the visit method for that specific type of element be invoked, but
additional methods |
| 5852 * for the supertypes of that element will also be invoked. For example, using a
n instance of this |
| 5853 * class to visit a [MethodElement] will cause the method |
| 5854 * [visitMethodElement] to be invoked but will also cause the methods |
| 5855 * [visitExecutableElement] and [visitElement] to be |
| 5856 * subsequently invoked. This allows visitors to be written that visit all execu
table elements |
| 5857 * without needing to override the visit method for each of the specific subclas
ses of |
| 5858 * [ExecutableElement]. |
| 5859 * |
| 5860 * Note, however, that unlike many visitors, element visitors visit objects base
d on the interfaces |
| 5861 * implemented by those elements. Because interfaces form a graph structure rath
er than a tree |
| 5862 * structure the way classes do, and because it is generally undesirable for an
object to be visited |
| 5863 * more than once, this class flattens the interface graph into a pseudo-tree. I
n particular, this |
| 5864 * class treats elements as if the element types were structured in the followin
g way: |
| 5865 * |
| 5866 * |
| 5867 * <pre> |
| 5868 * Element |
| 5869 * ClassElement |
| 5870 * CompilationUnitElement |
| 5871 * ExecutableElement |
| 5872 * ConstructorElement |
| 5873 * LocalElement |
| 5874 * FunctionElement |
| 5875 * MethodElement |
| 5876 * PropertyAccessorElement |
| 5877 * ExportElement |
| 5878 * HtmlElement |
| 5879 * ImportElement |
| 5880 * LabelElement |
| 5881 * LibraryElement |
| 5882 * MultiplyDefinedElement |
| 5883 * PrefixElement |
| 5884 * TypeAliasElement |
| 5885 * TypeParameterElement |
| 5886 * UndefinedElement |
| 5887 * VariableElement |
| 5888 * PropertyInducingElement |
| 5889 * FieldElement |
| 5890 * TopLevelVariableElement |
| 5891 * LocalElement |
| 5892 * LocalVariableElement |
| 5893 * ParameterElement |
| 5894 * FieldFormalParameterElement |
| 5895 * </pre> |
| 5896 * |
| 5897 * Subclasses that override a visit method must either invoke the overridden vis
it method or |
| 5898 * explicitly invoke the more general visit method. Failure to do so will cause
the visit methods |
| 5899 * for superclasses of the element to not be invoked and will cause the children
of the visited node |
| 5900 * to not be visited. |
| 5901 */ |
| 5902 class GeneralizingElementVisitor<R> implements ElementVisitor<R> { |
| 5903 @override |
| 5904 R visitAngularComponentElement(AngularComponentElement element) => visitAngula
rHasSelectorElement(element); |
| 5905 |
| 5906 @override |
| 5907 R visitAngularControllerElement(AngularControllerElement element) => visitAngu
larHasSelectorElement(element); |
| 5908 |
| 5909 @override |
| 5910 R visitAngularDirectiveElement(AngularDecoratorElement element) => visitAngula
rHasSelectorElement(element); |
| 5911 |
| 5912 R visitAngularElement(AngularElement element) => visitToolkitObjectElement(ele
ment); |
| 5913 |
| 5914 @override |
| 5915 R visitAngularFormatterElement(AngularFormatterElement element) => visitAngula
rElement(element); |
| 5916 |
| 5917 R visitAngularHasSelectorElement(AngularHasSelectorElement element) => visitAn
gularElement(element); |
| 5918 |
| 5919 @override |
| 5920 R visitAngularPropertyElement(AngularPropertyElement element) => visitAngularE
lement(element); |
| 5921 |
| 5922 @override |
| 5923 R visitAngularScopePropertyElement(AngularScopePropertyElement element) => vis
itAngularElement(element); |
| 5924 |
| 5925 @override |
| 5926 R visitAngularSelectorElement(AngularSelectorElement element) => visitAngularE
lement(element); |
| 5927 |
| 5928 @override |
| 5929 R visitAngularViewElement(AngularViewElement element) => visitAngularElement(e
lement); |
| 5930 |
| 5931 @override |
| 5932 R visitClassElement(ClassElement element) => visitElement(element); |
| 5933 |
| 5934 @override |
| 5935 R visitCompilationUnitElement(CompilationUnitElement element) => visitElement(
element); |
| 5936 |
| 5937 @override |
| 5938 R visitConstructorElement(ConstructorElement element) => visitExecutableElemen
t(element); |
| 5939 |
| 5940 R visitElement(Element element) { |
| 5941 element.visitChildren(this); |
| 5942 return null; |
| 5943 } |
| 5944 |
| 5945 @override |
| 5946 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => visitHt
mlScriptElement(element); |
| 5947 |
| 5948 R visitExecutableElement(ExecutableElement element) => visitElement(element); |
| 5949 |
| 5950 @override |
| 5951 R visitExportElement(ExportElement element) => visitElement(element); |
| 5952 |
| 5953 @override |
| 5954 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => visitHt
mlScriptElement(element); |
| 5955 |
| 5956 @override |
| 5957 R visitFieldElement(FieldElement element) => visitPropertyInducingElement(elem
ent); |
| 5958 |
| 5959 @override |
| 5960 R visitFieldFormalParameterElement(FieldFormalParameterElement element) => vis
itParameterElement(element); |
| 5961 |
| 5962 @override |
| 5963 R visitFunctionElement(FunctionElement element) => visitLocalElement(element); |
| 5964 |
| 5965 @override |
| 5966 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => visitElem
ent(element); |
| 5967 |
| 5968 @override |
| 5969 R visitHtmlElement(HtmlElement element) => visitElement(element); |
| 5970 |
| 5971 R visitHtmlScriptElement(HtmlScriptElement element) => visitElement(element); |
| 5972 |
| 5973 @override |
| 5974 R visitImportElement(ImportElement element) => visitElement(element); |
| 5975 |
| 5976 @override |
| 5977 R visitLabelElement(LabelElement element) => visitElement(element); |
| 5978 |
| 5979 @override |
| 5980 R visitLibraryElement(LibraryElement element) => visitElement(element); |
| 5981 |
| 5982 R visitLocalElement(LocalElement element) { |
| 5983 if (element is LocalVariableElement) { |
| 5984 return visitVariableElement(element); |
| 5985 } else if (element is ParameterElement) { |
| 5986 return visitVariableElement(element); |
| 5987 } else if (element is FunctionElement) { |
| 5988 return visitExecutableElement(element); |
| 5989 } |
| 5990 return null; |
| 5991 } |
| 5992 |
| 5993 @override |
| 5994 R visitLocalVariableElement(LocalVariableElement element) => visitLocalElement
(element); |
| 5995 |
| 5996 @override |
| 5997 R visitMethodElement(MethodElement element) => visitExecutableElement(element)
; |
| 5998 |
| 5999 @override |
| 6000 R visitMultiplyDefinedElement(MultiplyDefinedElement element) => visitElement(
element); |
| 6001 |
| 6002 @override |
| 6003 R visitParameterElement(ParameterElement element) => visitLocalElement(element
); |
| 6004 |
| 6005 @override |
| 6006 R visitPolymerAttributeElement(PolymerAttributeElement element) => visitPolyme
rElement(element); |
| 6007 |
| 6008 R visitPolymerElement(PolymerElement element) => visitToolkitObjectElement(ele
ment); |
| 6009 |
| 6010 @override |
| 6011 R visitPolymerTagDartElement(PolymerTagDartElement element) => visitPolymerEle
ment(element); |
| 6012 |
| 6013 @override |
| 6014 R visitPolymerTagHtmlElement(PolymerTagHtmlElement element) => visitPolymerEle
ment(element); |
| 6015 |
| 6016 @override |
| 6017 R visitPrefixElement(PrefixElement element) => visitElement(element); |
| 6018 |
| 6019 @override |
| 6020 R visitPropertyAccessorElement(PropertyAccessorElement element) => visitExecut
ableElement(element); |
| 6021 |
| 6022 R visitPropertyInducingElement(PropertyInducingElement element) => visitVariab
leElement(element); |
| 6023 |
| 6024 R visitToolkitObjectElement(ToolkitObjectElement element) => visitElement(elem
ent); |
| 6025 |
| 6026 @override |
| 6027 R visitTopLevelVariableElement(TopLevelVariableElement element) => visitProper
tyInducingElement(element); |
| 6028 |
| 6029 @override |
| 6030 R visitTypeParameterElement(TypeParameterElement element) => visitElement(elem
ent); |
| 6031 |
| 6032 R visitVariableElement(VariableElement element) => visitElement(element); |
| 6033 } |
| 6034 |
| 6035 /** |
| 6036 * Implementation of [AngularSelectorElement] based on presence of attribute. |
| 6037 */ |
| 6038 class HasAttributeSelectorElementImpl extends AngularSelectorElementImpl impleme
nts AngularHasAttributeSelectorElement { |
| 6039 HasAttributeSelectorElementImpl(String attributeName, int offset) : super(attr
ibuteName, offset); |
| 6040 |
| 6041 @override |
| 6042 bool apply(XmlTagNode node) { |
| 6043 String attributeName = name; |
| 6044 return node.getAttribute(attributeName) != null; |
| 6045 } |
| 6046 |
| 6047 @override |
| 6048 void appendTo(JavaStringBuilder builder) { |
| 6049 builder.append("["); |
| 6050 builder.append(name); |
| 6051 builder.append("]"); |
| 6052 } |
| 6053 } |
| 6054 |
| 6055 /** |
| 6056 * The interface `HideElementCombinator` defines the behavior of combinators tha
t cause some |
| 6057 * of the names in a namespace to be hidden when being imported. |
| 6058 */ |
| 6059 abstract class HideElementCombinator implements NamespaceCombinator { |
| 6060 /** |
| 6061 * Return an array containing the names that are not to be made visible in the
importing library |
| 6062 * even if they are defined in the imported library. |
| 6063 * |
| 6064 * @return the names from the imported library that are hidden from the import
ing library |
| 6065 */ |
| 6066 List<String> get hiddenNames; |
| 6067 } |
| 6068 |
| 6069 /** |
| 6070 * Instances of the class `HideElementCombinatorImpl` implement a |
| 6071 * [HideElementCombinator]. |
| 6072 */ |
| 6073 class HideElementCombinatorImpl implements HideElementCombinator { |
| 6074 /** |
| 6075 * The names that are not to be made visible in the importing library even if
they are defined in |
| 6076 * the imported library. |
| 6077 */ |
| 6078 List<String> hiddenNames = StringUtilities.EMPTY_ARRAY; |
| 6079 |
| 6080 @override |
| 6081 String toString() { |
| 6082 JavaStringBuilder builder = new JavaStringBuilder(); |
| 6083 builder.append("show "); |
| 6084 int count = hiddenNames.length; |
| 6085 for (int i = 0; i < count; i++) { |
| 6086 if (i > 0) { |
| 6087 builder.append(", "); |
| 6088 } |
| 6089 builder.append(hiddenNames[i]); |
| 6090 } |
| 6091 return builder.toString(); |
| 6092 } |
| 6093 } |
| 6094 |
| 6095 /** |
| 6096 * The interface `HtmlElement` defines the behavior of elements representing an
HTML file. |
| 6097 */ |
| 6098 abstract class HtmlElement implements Element { |
| 6099 /** |
| 6100 * Return the [CompilationUnitElement] associated with this Angular HTML file,
maybe |
| 6101 * `null` if not an Angular file. |
| 6102 */ |
| 6103 CompilationUnitElement get angularCompilationUnit; |
| 6104 |
| 6105 /** |
| 6106 * Return an array containing all of the [PolymerTagHtmlElement]s defined in t
he HTML file. |
| 6107 * |
| 6108 * @return the [PolymerTagHtmlElement]s elements in the HTML file (not `null`, |
| 6109 * contains no `null`s) |
| 6110 */ |
| 6111 List<PolymerTagHtmlElement> get polymerTags; |
| 6112 |
| 6113 /** |
| 6114 * Return an array containing all of the script elements contained in the HTML
file. This includes |
| 6115 * scripts with libraries that are defined by the content of a script tag as w
ell as libraries |
| 6116 * that are referenced in the {@core source} attribute of a script tag. |
| 6117 * |
| 6118 * @return the script elements in the HTML file (not `null`, contains no `null
`s) |
| 6119 */ |
| 6120 List<HtmlScriptElement> get scripts; |
| 6121 } |
| 6122 |
| 6123 /** |
| 6124 * Instances of the class `HtmlElementImpl` implement an [HtmlElement]. |
| 6125 */ |
| 6126 class HtmlElementImpl extends ElementImpl implements HtmlElement { |
| 6127 /** |
| 6128 * An empty array of HTML file elements. |
| 6129 */ |
| 6130 static List<HtmlElement> EMPTY_ARRAY = new List<HtmlElement>(0); |
| 6131 |
| 6132 /** |
| 6133 * The analysis context in which this library is defined. |
| 6134 */ |
| 6135 final AnalysisContext context; |
| 6136 |
| 6137 /** |
| 6138 * The scripts contained in or referenced from script tags in the HTML file. |
| 6139 */ |
| 6140 List<HtmlScriptElement> _scripts = HtmlScriptElementImpl.EMPTY_ARRAY; |
| 6141 |
| 6142 /** |
| 6143 * The [PolymerTagHtmlElement]s defined in the HTML file. |
| 6144 */ |
| 6145 List<PolymerTagHtmlElement> _polymerTags = PolymerTagHtmlElement.EMPTY_ARRAY; |
| 6146 |
| 6147 /** |
| 6148 * The source that corresponds to this HTML file. |
| 6149 */ |
| 6150 Source source; |
| 6151 |
| 6152 /** |
| 6153 * The element associated with Dart pieces in this HTML unit or `null` if the
receiver is |
| 6154 * not resolved. |
| 6155 */ |
| 6156 CompilationUnitElement angularCompilationUnit; |
| 6157 |
| 6158 /** |
| 6159 * Initialize a newly created HTML element to have the given name. |
| 6160 * |
| 6161 * @param context the analysis context in which the HTML file is defined |
| 6162 * @param name the name of this element |
| 6163 */ |
| 6164 HtmlElementImpl(this.context, String name) : super(name, -1); |
| 6165 |
| 6166 @override |
| 6167 accept(ElementVisitor visitor) => visitor.visitHtmlElement(this); |
| 6168 |
| 6169 @override |
| 6170 bool operator ==(Object object) { |
| 6171 if (identical(object, this)) { |
| 6172 return true; |
| 6173 } |
| 6174 if (object == null) { |
| 6175 return false; |
| 6176 } |
| 6177 return runtimeType == object.runtimeType && source == (object as HtmlElement
Impl).source; |
| 6178 } |
| 6179 |
| 6180 @override |
| 6181 ElementKind get kind => ElementKind.HTML; |
| 6182 |
| 6183 @override |
| 6184 List<PolymerTagHtmlElement> get polymerTags => _polymerTags; |
| 6185 |
| 6186 @override |
| 6187 List<HtmlScriptElement> get scripts => _scripts; |
| 6188 |
| 6189 @override |
| 6190 int get hashCode => source.hashCode; |
| 6191 |
| 6192 /** |
| 6193 * Set the [PolymerTagHtmlElement]s defined in the HTML file. |
| 6194 */ |
| 6195 void set polymerTags(List<PolymerTagHtmlElement> polymerTags) { |
| 6196 if (polymerTags.length == 0) { |
| 6197 this._polymerTags = PolymerTagHtmlElement.EMPTY_ARRAY; |
| 6198 return; |
| 6199 } |
| 6200 for (PolymerTagHtmlElement tag in polymerTags) { |
| 6201 (tag as PolymerTagHtmlElementImpl).enclosingElement = this; |
| 6202 } |
| 6203 this._polymerTags = polymerTags; |
| 6204 } |
| 6205 |
| 6206 /** |
| 6207 * Set the scripts contained in the HTML file to the given scripts. |
| 6208 * |
| 6209 * @param scripts the scripts |
| 6210 */ |
| 6211 void set scripts(List<HtmlScriptElement> scripts) { |
| 6212 if (scripts.length == 0) { |
| 6213 this._scripts = HtmlScriptElementImpl.EMPTY_ARRAY; |
| 6214 return; |
| 6215 } |
| 6216 for (HtmlScriptElement script in scripts) { |
| 6217 (script as HtmlScriptElementImpl).enclosingElement = this; |
| 6218 } |
| 6219 this._scripts = scripts; |
| 6220 } |
| 6221 |
| 6222 @override |
| 6223 void visitChildren(ElementVisitor visitor) { |
| 6224 super.visitChildren(visitor); |
| 6225 safelyVisitChildren(_scripts, visitor); |
| 6226 safelyVisitChildren(_polymerTags, visitor); |
| 6227 } |
| 6228 |
| 6229 @override |
| 6230 void appendTo(JavaStringBuilder builder) { |
| 6231 if (source == null) { |
| 6232 builder.append("{HTML file}"); |
| 6233 } else { |
| 6234 builder.append(source.fullName); |
| 6235 } |
| 6236 } |
| 6237 |
| 6238 @override |
| 6239 String get identifier => source.encoding; |
| 6240 } |
| 6241 |
| 6242 /** |
| 6243 * The interface `HtmlScriptElement` defines the behavior of elements representi
ng a script |
| 6244 * tag in an HTML file. |
| 6245 * |
| 6246 * @see EmbeddedHtmlScriptElement |
| 6247 * @see ExternalHtmlScriptElement |
| 6248 */ |
| 6249 abstract class HtmlScriptElement implements Element { |
| 6250 } |
| 6251 |
| 6252 /** |
| 6253 * Instances of the class `HtmlScriptElementImpl` implement an [HtmlScriptElemen
t]. |
| 6254 */ |
| 6255 abstract class HtmlScriptElementImpl extends ElementImpl implements HtmlScriptEl
ement { |
| 6256 /** |
| 6257 * An empty array of HTML script elements. |
| 6258 */ |
| 6259 static List<HtmlScriptElement> EMPTY_ARRAY = new List<HtmlScriptElement>(0); |
| 6260 |
| 6261 /** |
| 6262 * Initialize a newly created script element to have the specified tag name an
d offset. |
| 6263 * |
| 6264 * @param node the XML node from which this element is derived (not `null`) |
| 6265 */ |
| 6266 HtmlScriptElementImpl(XmlTagNode node) : super(node.tag, node.tagToken.offset)
; |
| 6267 } |
| 6268 |
| 6269 /** |
| 6270 * The interface `ImportElement` defines the behavior of objects representing in
formation |
| 6271 * about a single import directive within a library. |
| 6272 */ |
| 6273 abstract class ImportElement implements Element, UriReferencedElement { |
| 6274 /** |
| 6275 * An empty array of import elements. |
| 6276 */ |
| 6277 static final List<ImportElement> EMPTY_ARRAY = new List<ImportElement>(0); |
| 6278 |
| 6279 /** |
| 6280 * Return an array containing the combinators that were specified as part of t
he import directive |
| 6281 * in the order in which they were specified. |
| 6282 * |
| 6283 * @return the combinators specified in the import directive |
| 6284 */ |
| 6285 List<NamespaceCombinator> get combinators; |
| 6286 |
| 6287 /** |
| 6288 * Return the library that is imported into this library by this import direct
ive. |
| 6289 * |
| 6290 * @return the library that is imported into this library |
| 6291 */ |
| 6292 LibraryElement get importedLibrary; |
| 6293 |
| 6294 /** |
| 6295 * Return the prefix that was specified as part of the import directive, or `n
ull` if there |
| 6296 * was no prefix specified. |
| 6297 * |
| 6298 * @return the prefix that was specified as part of the import directive |
| 6299 */ |
| 6300 PrefixElement get prefix; |
| 6301 |
| 6302 /** |
| 6303 * Return the offset of the prefix of this import in the file that contains th
is import directive, |
| 6304 * or `-1` if this import is synthetic, does not have a prefix, or otherwise d
oes not have |
| 6305 * an offset. |
| 6306 * |
| 6307 * @return the offset of the prefix of this import |
| 6308 */ |
| 6309 int get prefixOffset; |
| 6310 |
| 6311 /** |
| 6312 * Return `true` if this import is for a deferred library. |
| 6313 * |
| 6314 * @return `true` if this import is for a deferred library |
| 6315 */ |
| 6316 bool get isDeferred; |
| 6317 } |
| 6318 |
| 6319 /** |
| 6320 * Instances of the class `ImportElementImpl` implement an [ImportElement]. |
| 6321 */ |
| 6322 class ImportElementImpl extends UriReferencedElementImpl implements ImportElemen
t { |
| 6323 /** |
| 6324 * The offset of the prefix of this import in the file that contains the this
import directive, or |
| 6325 * `-1` if this import is synthetic. |
| 6326 */ |
| 6327 int prefixOffset = 0; |
| 6328 |
| 6329 /** |
| 6330 * The library that is imported into this library by this import directive. |
| 6331 */ |
| 6332 LibraryElement importedLibrary; |
| 6333 |
| 6334 /** |
| 6335 * The combinators that were specified as part of the import directive in the
order in which they |
| 6336 * were specified. |
| 6337 */ |
| 6338 List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_ARRAY; |
| 6339 |
| 6340 /** |
| 6341 * The prefix that was specified as part of the import directive, or `null` if
there was no |
| 6342 * prefix specified. |
| 6343 */ |
| 6344 PrefixElement prefix; |
| 6345 |
| 6346 /** |
| 6347 * Initialize a newly created import element. |
| 6348 * |
| 6349 * @param offset the directive offset, may be `-1` if synthetic. |
| 6350 */ |
| 6351 ImportElementImpl(int offset) : super(null, offset); |
| 6352 |
| 6353 @override |
| 6354 accept(ElementVisitor visitor) => visitor.visitImportElement(this); |
| 6355 |
| 6356 @override |
| 6357 ElementKind get kind => ElementKind.IMPORT; |
| 6358 |
| 6359 @override |
| 6360 bool get isDeferred => hasModifier(Modifier.DEFERRED); |
| 6361 |
| 6362 /** |
| 6363 * Set whether this import is for a deferred library to correspond to the give
n value. |
| 6364 * |
| 6365 * @param isDeferred `true` if this import is for a deferred library |
| 6366 */ |
| 6367 void set deferred(bool isDeferred) { |
| 6368 setModifier(Modifier.DEFERRED, isDeferred); |
| 6369 } |
| 6370 |
| 6371 @override |
| 6372 void visitChildren(ElementVisitor visitor) { |
| 6373 super.visitChildren(visitor); |
| 6374 safelyVisitChild(prefix, visitor); |
| 6375 } |
| 6376 |
| 6377 @override |
| 6378 void appendTo(JavaStringBuilder builder) { |
| 6379 builder.append("import "); |
| 6380 (importedLibrary as LibraryElementImpl).appendTo(builder); |
| 6381 } |
| 6382 |
| 6383 @override |
| 6384 String get identifier => "${(importedLibrary as LibraryElementImpl).identifier
}@${nameOffset}"; |
| 6385 } |
| 6386 |
| 6387 /** |
| 6388 * The interface `InterfaceType` defines the behavior common to objects represen
ting the type |
| 6389 * introduced by either a class or an interface, or a reference to such a type. |
| 6390 */ |
| 6391 abstract class InterfaceType implements ParameterizedType { |
| 6392 /** |
| 6393 * An empty array of types. |
| 6394 */ |
| 6395 static final List<InterfaceType> EMPTY_ARRAY = new List<InterfaceType>(0); |
| 6396 |
| 6397 /** |
| 6398 * Return an array containing all of the accessors (getters and setters) decla
red in this type. |
| 6399 * |
| 6400 * @return the accessors declared in this type |
| 6401 */ |
| 6402 List<PropertyAccessorElement> get accessors; |
| 6403 |
| 6404 @override |
| 6405 ClassElement get element; |
| 6406 |
| 6407 /** |
| 6408 * Return the element representing the getter with the given name that is decl
ared in this class, |
| 6409 * or `null` if this class does not declare a getter with the given name. |
| 6410 * |
| 6411 * @param getterName the name of the getter to be returned |
| 6412 * @return the getter declared in this class with the given name |
| 6413 */ |
| 6414 PropertyAccessorElement getGetter(String getterName); |
| 6415 |
| 6416 /** |
| 6417 * Return an array containing all of the interfaces that are implemented by th
is interface. Note |
| 6418 * that this is <b>not</b>, in general, equivalent to getting the interfaces f
rom this type's |
| 6419 * element because the types returned by this method will have had their type
parameters replaced. |
| 6420 * |
| 6421 * @return the interfaces that are implemented by this type |
| 6422 */ |
| 6423 List<InterfaceType> get interfaces; |
| 6424 |
| 6425 /** |
| 6426 * Return the least upper bound of this type and the given type, or `null` if
there is no |
| 6427 * least upper bound. |
| 6428 * |
| 6429 * Given two interfaces <i>I</i> and <i>J</i>, let <i>S<sub>I</sub></i> be the
set of |
| 6430 * superinterfaces of <i>I<i>, let <i>S<sub>J</sub></i> be the set of superint
erfaces of <i>J</i> |
| 6431 * and let <i>S = (I ∪ S<sub>I</sub>) ∩ (J ∪ S<sub>J</sub>)</i>. F
urthermore, we |
| 6432 * define <i>S<sub>n</sub> = {T | T ∈ S ∧ depth(T) = n}</i> for any f
inite <i>n</i>, |
| 6433 * where <i>depth(T)</i> is the number of steps in the longest inheritance pat
h from <i>T</i> to |
| 6434 * <i>Object</i>. Let <i>q</i> be the largest number such that <i>S<sub>q</sub
></i> has |
| 6435 * cardinality one. The least upper bound of <i>I</i> and <i>J</i> is the sole
element of |
| 6436 * <i>S<sub>q</sub></i>. |
| 6437 * |
| 6438 * @param type the other type used to compute the least upper bound |
| 6439 * @return the least upper bound of this type and the given type |
| 6440 */ |
| 6441 @override |
| 6442 DartType getLeastUpperBound(DartType type); |
| 6443 |
| 6444 /** |
| 6445 * Return the element representing the method with the given name that is decl
ared in this class, |
| 6446 * or `null` if this class does not declare a method with the given name. |
| 6447 * |
| 6448 * @param methodName the name of the method to be returned |
| 6449 * @return the method declared in this class with the given name |
| 6450 */ |
| 6451 MethodElement getMethod(String methodName); |
| 6452 |
| 6453 /** |
| 6454 * Return an array containing all of the methods declared in this type. |
| 6455 * |
| 6456 * @return the methods declared in this type |
| 6457 */ |
| 6458 List<MethodElement> get methods; |
| 6459 |
| 6460 /** |
| 6461 * Return an array containing all of the mixins that are applied to the class
being extended in |
| 6462 * order to derive the superclass of this class. Note that this is <b>not</b>,
in general, |
| 6463 * equivalent to getting the mixins from this type's element because the types
returned by this |
| 6464 * method will have had their type parameters replaced. |
| 6465 * |
| 6466 * @return the mixins that are applied to derive the superclass of this class |
| 6467 */ |
| 6468 List<InterfaceType> get mixins; |
| 6469 |
| 6470 /** |
| 6471 * Return the element representing the setter with the given name that is decl
ared in this class, |
| 6472 * or `null` if this class does not declare a setter with the given name. |
| 6473 * |
| 6474 * @param setterName the name of the setter to be returned |
| 6475 * @return the setter declared in this class with the given name |
| 6476 */ |
| 6477 PropertyAccessorElement getSetter(String setterName); |
| 6478 |
| 6479 /** |
| 6480 * Return the type representing the superclass of this type, or null if this t
ype represents the |
| 6481 * class 'Object'. Note that this is <b>not</b>, in general, equivalent to get
ting the superclass |
| 6482 * from this type's element because the type returned by this method will have
had it's type |
| 6483 * parameters replaced. |
| 6484 * |
| 6485 * @return the superclass of this type |
| 6486 */ |
| 6487 InterfaceType get superclass; |
| 6488 |
| 6489 /** |
| 6490 * Return `true` if this type is a direct supertype of the given type. The imp
licit |
| 6491 * interface of class <i>I</i> is a direct supertype of the implicit interface
of class <i>J</i> |
| 6492 * iff: |
| 6493 * * <i>I</i> is Object, and <i>J</i> has no extends clause. |
| 6494 * * <i>I</i> is listed in the extends clause of <i>J</i>. |
| 6495 * * <i>I</i> is listed in the implements clause of <i>J</i>. |
| 6496 * * <i>I</i> is listed in the with clause of <i>J</i>. |
| 6497 * * <i>J</i> is a mixin application of the mixin of <i>I</i>. |
| 6498 * |
| 6499 * @param type the type being compared with this type |
| 6500 * @return `true` if this type is a direct supertype of the given type |
| 6501 */ |
| 6502 bool isDirectSupertypeOf(InterfaceType type); |
| 6503 |
| 6504 /** |
| 6505 * Return `true` if this type is more specific than the given type. An interfa
ce type |
| 6506 * <i>T</i> is more specific than an interface type <i>S</i>, written <i>T &la
quo; S</i>, if one |
| 6507 * of the following conditions is met: |
| 6508 * * Reflexivity: <i>T</i> is <i>S</i>. |
| 6509 * * <i>T</i> is bottom. |
| 6510 * * <i>S</i> is dynamic. |
| 6511 * * Direct supertype: <i>S</i> is a direct supertype of <i>T</i>. |
| 6512 * * <i>T</i> is a type parameter and <i>S</i> is the upper bound of <i>T</i>. |
| 6513 * * Covariance: <i>T</i> is of the form <i>I<T<sub>1</sub>, …, T<su
b>n</sub>></i> |
| 6514 * and S</i> is of the form <i>I<S<sub>1</sub>, …, S<sub>n</sub>>
</i> and |
| 6515 * <i>T<sub>i</sub> « S<sub>i</sub></i>, <i>1 <= i <= n</i>. |
| 6516 * * Transitivity: <i>T « U</i> and <i>U « S</i>. |
| 6517 * |
| 6518 * @param type the type being compared with this type |
| 6519 * @return `true` if this type is more specific than the given type |
| 6520 */ |
| 6521 @override |
| 6522 bool isMoreSpecificThan(DartType type); |
| 6523 |
| 6524 /** |
| 6525 * Return `true` if this type is a subtype of the given type. An interface typ
e <i>T</i> is |
| 6526 * a subtype of an interface type <i>S</i>, written <i>T</i> <: <i>S</i>, iff |
| 6527 * <i>[bottom/dynamic]T</i> « <i>S</i> (<i>T</i> is more specific than <
i>S</i>). If an |
| 6528 * interface type <i>I</i> includes a method named <i>call()</i>, and the type
of <i>call()</i> is |
| 6529 * the function type <i>F</i>, then <i>I</i> is considered to be a subtype of
<i>F</i>. |
| 6530 * |
| 6531 * @param type the type being compared with this type |
| 6532 * @return `true` if this type is a subtype of the given type |
| 6533 */ |
| 6534 @override |
| 6535 bool isSubtypeOf(DartType type); |
| 6536 |
| 6537 /** |
| 6538 * Return the element representing the constructor that results from looking u
p the given |
| 6539 * constructor in this class with respect to the given library, or `null` if t
he look up |
| 6540 * fails. The behavior of this method is defined by the Dart Language Specific
ation in section |
| 6541 * 12.11.1: <blockquote>If <i>e</i> is of the form <b>new</b> <i>T.id()</i> th
en let <i>q<i> be |
| 6542 * the constructor <i>T.id</i>, otherwise let <i>q<i> be the constructor <i>T<
i>. Otherwise, if |
| 6543 * <i>q</i> is not defined or not accessible, a NoSuchMethodException is throw
n. </blockquote> |
| 6544 * |
| 6545 * @param constructorName the name of the constructor being looked up |
| 6546 * @param library the library with respect to which the lookup is being perfor
med |
| 6547 * @return the result of looking up the given constructor in this class with r
espect to the given |
| 6548 * library |
| 6549 */ |
| 6550 ConstructorElement lookUpConstructor(String constructorName, LibraryElement li
brary); |
| 6551 |
| 6552 /** |
| 6553 * Return the element representing the getter that results from looking up the
given getter in |
| 6554 * this class with respect to the given library, or `null` if the look up fail
s. The |
| 6555 * behavior of this method is defined by the Dart Language Specification in se
ction 12.15.1: |
| 6556 * <blockquote>The result of looking up getter (respectively setter) <i>m</i>
in class <i>C</i> |
| 6557 * with respect to library <i>L</i> is: |
| 6558 * * If <i>C</i> declares an instance getter (respectively setter) named <i>m<
/i> that is |
| 6559 * accessible to <i>L</i>, then that getter (respectively setter) is the resul
t of the lookup. |
| 6560 * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lo
okup is the result |
| 6561 * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respec
t to <i>L</i>. |
| 6562 * Otherwise, we say that the lookup has failed. |
| 6563 * </blockquote> |
| 6564 * |
| 6565 * @param getterName the name of the getter being looked up |
| 6566 * @param library the library with respect to which the lookup is being perfor
med |
| 6567 * @return the result of looking up the given getter in this class with respec
t to the given |
| 6568 * library |
| 6569 */ |
| 6570 PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library
); |
| 6571 |
| 6572 /** |
| 6573 * Return the element representing the getter that results from looking up the
given getter in the |
| 6574 * superclass of this class with respect to the given library, or `null` if th
e look up |
| 6575 * fails. The behavior of this method is defined by the Dart Language Specific
ation in section |
| 6576 * 12.15.1: <blockquote>The result of looking up getter (respectively setter)
<i>m</i> in class |
| 6577 * <i>C</i> with respect to library <i>L</i> is: |
| 6578 * * If <i>C</i> declares an instance getter (respectively setter) named <i>m<
/i> that is |
| 6579 * accessible to <i>L</i>, then that getter (respectively setter) is the resul
t of the lookup. |
| 6580 * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lo
okup is the result |
| 6581 * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respec
t to <i>L</i>. |
| 6582 * Otherwise, we say that the lookup has failed. |
| 6583 * </blockquote> |
| 6584 * |
| 6585 * @param getterName the name of the getter being looked up |
| 6586 * @param library the library with respect to which the lookup is being perfor
med |
| 6587 * @return the result of looking up the given getter in this class with respec
t to the given |
| 6588 * library |
| 6589 */ |
| 6590 PropertyAccessorElement lookUpGetterInSuperclass(String getterName, LibraryEle
ment library); |
| 6591 |
| 6592 /** |
| 6593 * Return the element representing the method that results from looking up the
given method in |
| 6594 * this class with respect to the given library, or `null` if the look up fail
s. The |
| 6595 * behavior of this method is defined by the Dart Language Specification in se
ction 12.15.1: |
| 6596 * <blockquote> The result of looking up method <i>m</i> in class <i>C</i> wit
h respect to library |
| 6597 * <i>L</i> is: |
| 6598 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible
to <i>L</i>, then |
| 6599 * that method is the result of the lookup. Otherwise, if <i>C</i> has a super
class <i>S</i>, then |
| 6600 * the result of the lookup is the result of looking up method <i>m</i> in <i>
S</i> with respect |
| 6601 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 6602 * </blockquote> |
| 6603 * |
| 6604 * @param methodName the name of the method being looked up |
| 6605 * @param library the library with respect to which the lookup is being perfor
med |
| 6606 * @return the result of looking up the given method in this class with respec
t to the given |
| 6607 * library |
| 6608 */ |
| 6609 MethodElement lookUpMethod(String methodName, LibraryElement library); |
| 6610 |
| 6611 /** |
| 6612 * Return the element representing the method that results from looking up the
given method in the |
| 6613 * superclass of this class with respect to the given library, or `null` if th
e look up |
| 6614 * fails. The behavior of this method is defined by the Dart Language Specific
ation in section |
| 6615 * 12.15.1: <blockquote> The result of looking up method <i>m</i> in class <i>
C</i> with respect |
| 6616 * to library <i>L</i> is: |
| 6617 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible
to <i>L</i>, then |
| 6618 * that method is the result of the lookup. Otherwise, if <i>C</i> has a super
class <i>S</i>, then |
| 6619 * the result of the lookup is the result of looking up method <i>m</i> in <i>
S</i> with respect |
| 6620 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 6621 * </blockquote> |
| 6622 * |
| 6623 * @param methodName the name of the method being looked up |
| 6624 * @param library the library with respect to which the lookup is being perfor
med |
| 6625 * @return the result of looking up the given method in this class with respec
t to the given |
| 6626 * library |
| 6627 */ |
| 6628 MethodElement lookUpMethodInSuperclass(String methodName, LibraryElement libra
ry); |
| 6629 |
| 6630 /** |
| 6631 * Return the element representing the setter that results from looking up the
given setter in |
| 6632 * this class with respect to the given library, or `null` if the look up fail
s. The |
| 6633 * behavior of this method is defined by the Dart Language Specification in se
ction 12.16: |
| 6634 * <blockquote> The result of looking up getter (respectively setter) <i>m</i>
in class <i>C</i> |
| 6635 * with respect to library <i>L</i> is: |
| 6636 * * If <i>C</i> declares an instance getter (respectively setter) named <i>m<
/i> that is |
| 6637 * accessible to <i>L</i>, then that getter (respectively setter) is the resul
t of the lookup. |
| 6638 * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lo
okup is the result |
| 6639 * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respec
t to <i>L</i>. |
| 6640 * Otherwise, we say that the lookup has failed. |
| 6641 * </blockquote> |
| 6642 * |
| 6643 * @param setterName the name of the setter being looked up |
| 6644 * @param library the library with respect to which the lookup is being perfor
med |
| 6645 * @return the result of looking up the given setter in this class with respec
t to the given |
| 6646 * library |
| 6647 */ |
| 6648 PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library
); |
| 6649 |
| 6650 /** |
| 6651 * Return the element representing the setter that results from looking up the
given setter in the |
| 6652 * superclass of this class with respect to the given library, or `null` if th
e look up |
| 6653 * fails. The behavior of this method is defined by the Dart Language Specific
ation in section |
| 6654 * 12.16: <blockquote> The result of looking up getter (respectively setter) <
i>m</i> in class |
| 6655 * <i>C</i> with respect to library <i>L</i> is: |
| 6656 * * If <i>C</i> declares an instance getter (respectively setter) named <i>m<
/i> that is |
| 6657 * accessible to <i>L</i>, then that getter (respectively setter) is the resul
t of the lookup. |
| 6658 * Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lo
okup is the result |
| 6659 * of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respec
t to <i>L</i>. |
| 6660 * Otherwise, we say that the lookup has failed. |
| 6661 * </blockquote> |
| 6662 * |
| 6663 * @param setterName the name of the setter being looked up |
| 6664 * @param library the library with respect to which the lookup is being perfor
med |
| 6665 * @return the result of looking up the given setter in this class with respec
t to the given |
| 6666 * library |
| 6667 */ |
| 6668 PropertyAccessorElement lookUpSetterInSuperclass(String setterName, LibraryEle
ment library); |
| 6669 |
| 6670 /** |
| 6671 * Return the type resulting from substituting the given arguments for this ty
pe's parameters. |
| 6672 * This is fully equivalent to `substitute(argumentTypes, getTypeArguments())`
. |
| 6673 * |
| 6674 * @param argumentTypes the actual type arguments being substituted for the ty
pe parameters |
| 6675 * @return the result of performing the substitution |
| 6676 */ |
| 6677 InterfaceType substitute4(List<DartType> argumentTypes); |
| 6678 |
| 6679 @override |
| 6680 InterfaceType substitute2(List<DartType> argumentTypes, List<DartType> paramet
erTypes); |
| 6681 } |
| 6682 |
| 6683 /** |
| 6684 * Instances of the class `InterfaceTypeImpl` defines the behavior common to obj
ects |
| 6685 * representing the type introduced by either a class or an interface, or a refe
rence to such a |
| 6686 * type. |
| 6687 */ |
| 6688 class InterfaceTypeImpl extends TypeImpl implements InterfaceType { |
| 6689 /** |
| 6690 * This method computes the longest inheritance path from some passed [Type] t
o Object. |
| 6691 * |
| 6692 * @param type the [Type] to compute the longest inheritance path of from the
passed |
| 6693 * [Type] to Object |
| 6694 * @return the computed longest inheritance path to Object |
| 6695 * @see InterfaceType#getLeastUpperBound(Type) |
| 6696 */ |
| 6697 static int computeLongestInheritancePathToObject(InterfaceType type) => _compu
teLongestInheritancePathToObject(type, 0, new HashSet<ClassElement>()); |
| 6698 |
| 6699 /** |
| 6700 * Returns the set of all superinterfaces of the passed [Type]. |
| 6701 * |
| 6702 * @param type the [Type] to compute the set of superinterfaces of |
| 6703 * @return the [Set] of superinterfaces of the passed [Type] |
| 6704 * @see #getLeastUpperBound(Type) |
| 6705 */ |
| 6706 static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) => _com
puteSuperinterfaceSet(type, new HashSet<InterfaceType>()); |
| 6707 |
| 6708 /** |
| 6709 * This method computes the longest inheritance path from some passed [Type] t
o Object. This |
| 6710 * method calls itself recursively, callers should use the public method |
| 6711 * [computeLongestInheritancePathToObject]. |
| 6712 * |
| 6713 * @param type the [Type] to compute the longest inheritance path of from the
passed |
| 6714 * [Type] to Object |
| 6715 * @param depth a field used recursively |
| 6716 * @param visitedClasses the classes that have already been visited |
| 6717 * @return the computed longest inheritance path to Object |
| 6718 * @see #computeLongestInheritancePathToObject(Type) |
| 6719 * @see #getLeastUpperBound(Type) |
| 6720 */ |
| 6721 static int _computeLongestInheritancePathToObject(InterfaceType type, int dept
h, HashSet<ClassElement> visitedClasses) { |
| 6722 ClassElement classElement = type.element; |
| 6723 // Object case |
| 6724 if (classElement.supertype == null || visitedClasses.contains(classElement))
{ |
| 6725 return depth; |
| 6726 } |
| 6727 int longestPath = 1; |
| 6728 try { |
| 6729 visitedClasses.add(classElement); |
| 6730 List<InterfaceType> superinterfaces = classElement.interfaces; |
| 6731 int pathLength; |
| 6732 if (superinterfaces.length > 0) { |
| 6733 // loop through each of the superinterfaces recursively calling this met
hod and keeping track |
| 6734 // of the longest path to return |
| 6735 for (InterfaceType superinterface in superinterfaces) { |
| 6736 pathLength = _computeLongestInheritancePathToObject(superinterface, de
pth + 1, visitedClasses); |
| 6737 if (pathLength > longestPath) { |
| 6738 longestPath = pathLength; |
| 6739 } |
| 6740 } |
| 6741 } |
| 6742 // finally, perform this same check on the super type |
| 6743 // TODO(brianwilkerson) Does this also need to add in the number of mixin
classes? |
| 6744 InterfaceType supertype = classElement.supertype; |
| 6745 pathLength = _computeLongestInheritancePathToObject(supertype, depth + 1,
visitedClasses); |
| 6746 if (pathLength > longestPath) { |
| 6747 longestPath = pathLength; |
| 6748 } |
| 6749 } finally { |
| 6750 visitedClasses.remove(classElement); |
| 6751 } |
| 6752 return longestPath; |
| 6753 } |
| 6754 |
| 6755 /** |
| 6756 * Returns the set of all superinterfaces of the passed [Type]. This is a recu
rsive method, |
| 6757 * callers should call the public [computeSuperinterfaceSet]. |
| 6758 * |
| 6759 * @param type the [Type] to compute the set of superinterfaces of |
| 6760 * @param set a [HashSet] used recursively by this method |
| 6761 * @return the [Set] of superinterfaces of the passed [Type] |
| 6762 * @see #computeSuperinterfaceSet(Type) |
| 6763 * @see #getLeastUpperBound(Type) |
| 6764 */ |
| 6765 static Set<InterfaceType> _computeSuperinterfaceSet(InterfaceType type, HashSe
t<InterfaceType> set) { |
| 6766 Element element = type.element; |
| 6767 if (element != null) { |
| 6768 List<InterfaceType> superinterfaces = type.interfaces; |
| 6769 for (InterfaceType superinterface in superinterfaces) { |
| 6770 if (set.add(superinterface)) { |
| 6771 _computeSuperinterfaceSet(superinterface, set); |
| 6772 } |
| 6773 } |
| 6774 InterfaceType supertype = type.superclass; |
| 6775 if (supertype != null) { |
| 6776 if (set.add(supertype)) { |
| 6777 _computeSuperinterfaceSet(supertype, set); |
| 6778 } |
| 6779 } |
| 6780 } |
| 6781 return set; |
| 6782 } |
| 6783 |
| 6784 /** |
| 6785 * Return the intersection of the given sets of types, where intersection is b
ased on the equality |
| 6786 * of the types themselves. |
| 6787 * |
| 6788 * @param first the first set of types to be intersected |
| 6789 * @param second the second set of types to be intersected |
| 6790 * @return the intersection of the given sets of types |
| 6791 */ |
| 6792 static List<InterfaceType> _intersection(Set<InterfaceType> first, Set<Interfa
ceType> second) { |
| 6793 Set<InterfaceType> result = new HashSet<InterfaceType>.from(first); |
| 6794 result.retainAll(second); |
| 6795 return new List.from(result); |
| 6796 } |
| 6797 |
| 6798 /** |
| 6799 * Return the "least upper bound" of the given types under the assumption that
the types have the |
| 6800 * same element and differ only in terms of the type arguments. The resulting
type is composed by |
| 6801 * comparing the corresponding type arguments, keeping those that are the same
, and using |
| 6802 * 'dynamic' for those that are different. |
| 6803 * |
| 6804 * @param firstType the first type |
| 6805 * @param secondType the second type |
| 6806 * @return the "least upper bound" of the given types |
| 6807 */ |
| 6808 static InterfaceType _leastUpperBound(InterfaceType firstType, InterfaceType s
econdType) { |
| 6809 if (firstType == secondType) { |
| 6810 return firstType; |
| 6811 } |
| 6812 List<DartType> firstArguments = firstType.typeArguments; |
| 6813 List<DartType> secondArguments = secondType.typeArguments; |
| 6814 int argumentCount = firstArguments.length; |
| 6815 if (argumentCount == 0) { |
| 6816 return firstType; |
| 6817 } |
| 6818 List<DartType> lubArguments = new List<DartType>(argumentCount); |
| 6819 for (int i = 0; i < argumentCount; i++) { |
| 6820 // |
| 6821 // Ideally we would take the least upper bound of the two argument types,
but this can cause |
| 6822 // an infinite recursion (such as when finding the least upper bound of St
ring and num). |
| 6823 // |
| 6824 if (firstArguments[i] == secondArguments[i]) { |
| 6825 lubArguments[i] = firstArguments[i]; |
| 6826 } |
| 6827 if (lubArguments[i] == null) { |
| 6828 lubArguments[i] = DynamicTypeImpl.instance; |
| 6829 } |
| 6830 } |
| 6831 InterfaceTypeImpl lub = new InterfaceTypeImpl.con1(firstType.element); |
| 6832 lub.typeArguments = lubArguments; |
| 6833 return lub; |
| 6834 } |
| 6835 |
| 6836 /** |
| 6837 * An array containing the actual types of the type arguments. |
| 6838 */ |
| 6839 List<DartType> typeArguments = TypeImpl.EMPTY_ARRAY; |
| 6840 |
| 6841 /** |
| 6842 * Initialize a newly created type to be declared by the given element. |
| 6843 * |
| 6844 * @param element the element representing the declaration of the type |
| 6845 */ |
| 6846 InterfaceTypeImpl.con1(ClassElement element) : super(element, element.displayN
ame); |
| 6847 |
| 6848 /** |
| 6849 * Initialize a newly created type to have the given name. This constructor sh
ould only be used in |
| 6850 * cases where there is no declaration of the type. |
| 6851 * |
| 6852 * @param name the name of the type |
| 6853 */ |
| 6854 InterfaceTypeImpl.con2(String name) : super(null, name); |
| 6855 |
| 6856 @override |
| 6857 bool operator ==(Object object) => internalEquals(object, new HashSet<ElementP
air>()); |
| 6858 |
| 6859 @override |
| 6860 List<PropertyAccessorElement> get accessors { |
| 6861 List<PropertyAccessorElement> accessors = element.accessors; |
| 6862 List<PropertyAccessorElement> members = new List<PropertyAccessorElement>(ac
cessors.length); |
| 6863 for (int i = 0; i < accessors.length; i++) { |
| 6864 members[i] = PropertyAccessorMember.from(accessors[i], this); |
| 6865 } |
| 6866 return members; |
| 6867 } |
| 6868 |
| 6869 @override |
| 6870 String get displayName { |
| 6871 String name = this.name; |
| 6872 List<DartType> typeArguments = this.typeArguments; |
| 6873 bool allDynamic = true; |
| 6874 for (DartType type in typeArguments) { |
| 6875 if (type != null && !type.isDynamic) { |
| 6876 allDynamic = false; |
| 6877 break; |
| 6878 } |
| 6879 } |
| 6880 // If there is at least one non-dynamic type, then list them out |
| 6881 if (!allDynamic) { |
| 6882 JavaStringBuilder builder = new JavaStringBuilder(); |
| 6883 builder.append(name); |
| 6884 builder.append("<"); |
| 6885 for (int i = 0; i < typeArguments.length; i++) { |
| 6886 if (i != 0) { |
| 6887 builder.append(", "); |
| 6888 } |
| 6889 DartType typeArg = typeArguments[i]; |
| 6890 builder.append(typeArg.displayName); |
| 6891 } |
| 6892 builder.append(">"); |
| 6893 name = builder.toString(); |
| 6894 } |
| 6895 return name; |
| 6896 } |
| 6897 |
| 6898 @override |
| 6899 ClassElement get element => super.element as ClassElement; |
| 6900 |
| 6901 @override |
| 6902 PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember
.from((element as ClassElementImpl).getGetter(getterName), this); |
| 6903 |
| 6904 @override |
| 6905 List<InterfaceType> get interfaces { |
| 6906 ClassElement classElement = element; |
| 6907 List<InterfaceType> interfaces = classElement.interfaces; |
| 6908 List<TypeParameterElement> typeParameters = classElement.typeParameters; |
| 6909 List<DartType> parameterTypes = classElement.type.typeArguments; |
| 6910 if (typeParameters.length == 0) { |
| 6911 return interfaces; |
| 6912 } |
| 6913 int count = interfaces.length; |
| 6914 List<InterfaceType> typedInterfaces = new List<InterfaceType>(count); |
| 6915 for (int i = 0; i < count; i++) { |
| 6916 typedInterfaces[i] = interfaces[i].substitute2(typeArguments, parameterTyp
es); |
| 6917 } |
| 6918 return typedInterfaces; |
| 6919 } |
| 6920 |
| 6921 @override |
| 6922 DartType getLeastUpperBound(DartType type) { |
| 6923 // quick check for self |
| 6924 if (identical(type, this)) { |
| 6925 return this; |
| 6926 } |
| 6927 // dynamic |
| 6928 DartType dynamicType = DynamicTypeImpl.instance; |
| 6929 if (identical(this, dynamicType) || identical(type, dynamicType)) { |
| 6930 return dynamicType; |
| 6931 } |
| 6932 // TODO (jwren) opportunity here for a better, faster algorithm if this turn
s out to be a bottle-neck |
| 6933 if (type is! InterfaceType) { |
| 6934 return null; |
| 6935 } |
| 6936 // new names to match up with the spec |
| 6937 InterfaceType i = this; |
| 6938 InterfaceType j = type as InterfaceType; |
| 6939 // compute set of supertypes |
| 6940 Set<InterfaceType> si = computeSuperinterfaceSet(i); |
| 6941 Set<InterfaceType> sj = computeSuperinterfaceSet(j); |
| 6942 // union si with i and sj with j |
| 6943 si.add(i); |
| 6944 sj.add(j); |
| 6945 // compute intersection, reference as set 's' |
| 6946 List<InterfaceType> s = _intersection(si, sj); |
| 6947 // for each element in Set s, compute the largest inheritance path to Object |
| 6948 List<int> depths = new List<int>.filled(s.length, 0); |
| 6949 int maxDepth = 0; |
| 6950 for (int n = 0; n < s.length; n++) { |
| 6951 depths[n] = computeLongestInheritancePathToObject(s[n]); |
| 6952 if (depths[n] > maxDepth) { |
| 6953 maxDepth = depths[n]; |
| 6954 } |
| 6955 } |
| 6956 // ensure that the currently computed maxDepth is unique, |
| 6957 // otherwise, decrement and test for uniqueness again |
| 6958 for (; maxDepth >= 0; maxDepth--) { |
| 6959 int indexOfLeastUpperBound = -1; |
| 6960 int numberOfTypesAtMaxDepth = 0; |
| 6961 for (int m = 0; m < depths.length; m++) { |
| 6962 if (depths[m] == maxDepth) { |
| 6963 numberOfTypesAtMaxDepth++; |
| 6964 indexOfLeastUpperBound = m; |
| 6965 } |
| 6966 } |
| 6967 if (numberOfTypesAtMaxDepth == 1) { |
| 6968 return s[indexOfLeastUpperBound]; |
| 6969 } |
| 6970 } |
| 6971 // illegal state, log and return null- Object at maxDepth == 0 should always
return itself as |
| 6972 // the least upper bound. |
| 6973 // TODO (jwren) log the error state |
| 6974 return null; |
| 6975 } |
| 6976 |
| 6977 @override |
| 6978 MethodElement getMethod(String methodName) => MethodMember.from((element as Cl
assElementImpl).getMethod(methodName), this); |
| 6979 |
| 6980 @override |
| 6981 List<MethodElement> get methods { |
| 6982 List<MethodElement> methods = element.methods; |
| 6983 List<MethodElement> members = new List<MethodElement>(methods.length); |
| 6984 for (int i = 0; i < methods.length; i++) { |
| 6985 members[i] = MethodMember.from(methods[i], this); |
| 6986 } |
| 6987 return members; |
| 6988 } |
| 6989 |
| 6990 @override |
| 6991 List<InterfaceType> get mixins { |
| 6992 ClassElement classElement = element; |
| 6993 List<InterfaceType> mixins = classElement.mixins; |
| 6994 List<TypeParameterElement> typeParameters = classElement.typeParameters; |
| 6995 List<DartType> parameterTypes = classElement.type.typeArguments; |
| 6996 if (typeParameters.length == 0) { |
| 6997 return mixins; |
| 6998 } |
| 6999 int count = mixins.length; |
| 7000 List<InterfaceType> typedMixins = new List<InterfaceType>(count); |
| 7001 for (int i = 0; i < count; i++) { |
| 7002 typedMixins[i] = mixins[i].substitute2(typeArguments, parameterTypes); |
| 7003 } |
| 7004 return typedMixins; |
| 7005 } |
| 7006 |
| 7007 @override |
| 7008 PropertyAccessorElement getSetter(String setterName) => PropertyAccessorMember
.from((element as ClassElementImpl).getSetter(setterName), this); |
| 7009 |
| 7010 @override |
| 7011 InterfaceType get superclass { |
| 7012 ClassElement classElement = element; |
| 7013 InterfaceType supertype = classElement.supertype; |
| 7014 if (supertype == null) { |
| 7015 return null; |
| 7016 } |
| 7017 List<DartType> typeParameters = classElement.type.typeArguments; |
| 7018 if (typeArguments.length == 0 || typeArguments.length != typeParameters.leng
th) { |
| 7019 return supertype; |
| 7020 } |
| 7021 return supertype.substitute2(typeArguments, typeParameters); |
| 7022 } |
| 7023 |
| 7024 @override |
| 7025 List<TypeParameterElement> get typeParameters => element.typeParameters; |
| 7026 |
| 7027 @override |
| 7028 int get hashCode { |
| 7029 ClassElement element = this.element; |
| 7030 if (element == null) { |
| 7031 return 0; |
| 7032 } |
| 7033 return element.hashCode; |
| 7034 } |
| 7035 |
| 7036 @override |
| 7037 bool get isDartCoreFunction { |
| 7038 ClassElement element = this.element; |
| 7039 if (element == null) { |
| 7040 return false; |
| 7041 } |
| 7042 return element.name == "Function" && element.library.isDartCore; |
| 7043 } |
| 7044 |
| 7045 @override |
| 7046 bool isDirectSupertypeOf(InterfaceType type) { |
| 7047 InterfaceType i = this; |
| 7048 InterfaceType j = type; |
| 7049 ClassElement jElement = j.element; |
| 7050 InterfaceType supertype = jElement.supertype; |
| 7051 // |
| 7052 // If J has no direct supertype then it is Object, and Object has no direct
supertypes. |
| 7053 // |
| 7054 if (supertype == null) { |
| 7055 return false; |
| 7056 } |
| 7057 // |
| 7058 // I is listed in the extends clause of J. |
| 7059 // |
| 7060 List<DartType> jArgs = j.typeArguments; |
| 7061 List<DartType> jVars = jElement.type.typeArguments; |
| 7062 supertype = supertype.substitute2(jArgs, jVars); |
| 7063 if (supertype == i) { |
| 7064 return true; |
| 7065 } |
| 7066 // |
| 7067 // I is listed in the implements clause of J. |
| 7068 // |
| 7069 for (InterfaceType interfaceType in jElement.interfaces) { |
| 7070 interfaceType = interfaceType.substitute2(jArgs, jVars); |
| 7071 if (interfaceType == i) { |
| 7072 return true; |
| 7073 } |
| 7074 } |
| 7075 // |
| 7076 // I is listed in the with clause of J. |
| 7077 // |
| 7078 for (InterfaceType mixinType in jElement.mixins) { |
| 7079 mixinType = mixinType.substitute2(jArgs, jVars); |
| 7080 if (mixinType == i) { |
| 7081 return true; |
| 7082 } |
| 7083 } |
| 7084 // |
| 7085 // J is a mixin application of the mixin of I. |
| 7086 // |
| 7087 // TODO(brianwilkerson) Determine whether this needs to be implemented or wh
ether it is covered |
| 7088 // by the case above. |
| 7089 return false; |
| 7090 } |
| 7091 |
| 7092 @override |
| 7093 bool get isObject => element.supertype == null; |
| 7094 |
| 7095 @override |
| 7096 ConstructorElement lookUpConstructor(String constructorName, LibraryElement li
brary) { |
| 7097 // prepare base ConstructorElement |
| 7098 ConstructorElement constructorElement; |
| 7099 if (constructorName == null) { |
| 7100 constructorElement = element.unnamedConstructor; |
| 7101 } else { |
| 7102 constructorElement = element.getNamedConstructor(constructorName); |
| 7103 } |
| 7104 // not found or not accessible |
| 7105 if (constructorElement == null || !constructorElement.isAccessibleIn(library
)) { |
| 7106 return null; |
| 7107 } |
| 7108 // return member |
| 7109 return ConstructorMember.from(constructorElement, this); |
| 7110 } |
| 7111 |
| 7112 @override |
| 7113 PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library
) { |
| 7114 PropertyAccessorElement element = getGetter(getterName); |
| 7115 if (element != null && element.isAccessibleIn(library)) { |
| 7116 return element; |
| 7117 } |
| 7118 return lookUpGetterInSuperclass(getterName, library); |
| 7119 } |
| 7120 |
| 7121 @override |
| 7122 PropertyAccessorElement lookUpGetterInSuperclass(String getterName, LibraryEle
ment library) { |
| 7123 for (InterfaceType mixin in mixins) { |
| 7124 PropertyAccessorElement element = mixin.getGetter(getterName); |
| 7125 if (element != null && element.isAccessibleIn(library)) { |
| 7126 return element; |
| 7127 } |
| 7128 } |
| 7129 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 7130 InterfaceType supertype = superclass; |
| 7131 ClassElement supertypeElement = supertype == null ? null : supertype.element
; |
| 7132 while (supertype != null && !visitedClasses.contains(supertypeElement)) { |
| 7133 visitedClasses.add(supertypeElement); |
| 7134 PropertyAccessorElement element = supertype.getGetter(getterName); |
| 7135 if (element != null && element.isAccessibleIn(library)) { |
| 7136 return element; |
| 7137 } |
| 7138 for (InterfaceType mixin in supertype.mixins) { |
| 7139 element = mixin.getGetter(getterName); |
| 7140 if (element != null && element.isAccessibleIn(library)) { |
| 7141 return element; |
| 7142 } |
| 7143 } |
| 7144 supertype = supertype.superclass; |
| 7145 supertypeElement = supertype == null ? null : supertype.element; |
| 7146 } |
| 7147 return null; |
| 7148 } |
| 7149 |
| 7150 @override |
| 7151 MethodElement lookUpMethod(String methodName, LibraryElement library) { |
| 7152 MethodElement element = getMethod(methodName); |
| 7153 if (element != null && element.isAccessibleIn(library)) { |
| 7154 return element; |
| 7155 } |
| 7156 return lookUpMethodInSuperclass(methodName, library); |
| 7157 } |
| 7158 |
| 7159 @override |
| 7160 MethodElement lookUpMethodInSuperclass(String methodName, LibraryElement libra
ry) { |
| 7161 for (InterfaceType mixin in mixins) { |
| 7162 MethodElement element = mixin.getMethod(methodName); |
| 7163 if (element != null && element.isAccessibleIn(library)) { |
| 7164 return element; |
| 7165 } |
| 7166 } |
| 7167 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 7168 InterfaceType supertype = superclass; |
| 7169 ClassElement supertypeElement = supertype == null ? null : supertype.element
; |
| 7170 while (supertype != null && !visitedClasses.contains(supertypeElement)) { |
| 7171 visitedClasses.add(supertypeElement); |
| 7172 MethodElement element = supertype.getMethod(methodName); |
| 7173 if (element != null && element.isAccessibleIn(library)) { |
| 7174 return element; |
| 7175 } |
| 7176 for (InterfaceType mixin in supertype.mixins) { |
| 7177 element = mixin.getMethod(methodName); |
| 7178 if (element != null && element.isAccessibleIn(library)) { |
| 7179 return element; |
| 7180 } |
| 7181 } |
| 7182 supertype = supertype.superclass; |
| 7183 supertypeElement = supertype == null ? null : supertype.element; |
| 7184 } |
| 7185 return null; |
| 7186 } |
| 7187 |
| 7188 @override |
| 7189 PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library
) { |
| 7190 PropertyAccessorElement element = getSetter(setterName); |
| 7191 if (element != null && element.isAccessibleIn(library)) { |
| 7192 return element; |
| 7193 } |
| 7194 return lookUpSetterInSuperclass(setterName, library); |
| 7195 } |
| 7196 |
| 7197 @override |
| 7198 PropertyAccessorElement lookUpSetterInSuperclass(String setterName, LibraryEle
ment library) { |
| 7199 for (InterfaceType mixin in mixins) { |
| 7200 PropertyAccessorElement element = mixin.getSetter(setterName); |
| 7201 if (element != null && element.isAccessibleIn(library)) { |
| 7202 return element; |
| 7203 } |
| 7204 } |
| 7205 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 7206 InterfaceType supertype = superclass; |
| 7207 ClassElement supertypeElement = supertype == null ? null : supertype.element
; |
| 7208 while (supertype != null && !visitedClasses.contains(supertypeElement)) { |
| 7209 visitedClasses.add(supertypeElement); |
| 7210 PropertyAccessorElement element = supertype.getSetter(setterName); |
| 7211 if (element != null && element.isAccessibleIn(library)) { |
| 7212 return element; |
| 7213 } |
| 7214 for (InterfaceType mixin in supertype.mixins) { |
| 7215 element = mixin.getSetter(setterName); |
| 7216 if (element != null && element.isAccessibleIn(library)) { |
| 7217 return element; |
| 7218 } |
| 7219 } |
| 7220 supertype = supertype.superclass; |
| 7221 supertypeElement = supertype == null ? null : supertype.element; |
| 7222 } |
| 7223 return null; |
| 7224 } |
| 7225 |
| 7226 @override |
| 7227 InterfaceTypeImpl substitute4(List<DartType> argumentTypes) => substitute2(arg
umentTypes, typeArguments); |
| 7228 |
| 7229 @override |
| 7230 InterfaceTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> par
ameterTypes) { |
| 7231 if (argumentTypes.length != parameterTypes.length) { |
| 7232 throw new IllegalArgumentException("argumentTypes.length (${argumentTypes.
length}) != parameterTypes.length (${parameterTypes.length})"); |
| 7233 } |
| 7234 if (argumentTypes.length == 0 || typeArguments.length == 0) { |
| 7235 return this; |
| 7236 } |
| 7237 List<DartType> newTypeArguments = TypeImpl.substitute(typeArguments, argumen
tTypes, parameterTypes); |
| 7238 if (JavaArrays.equals(newTypeArguments, typeArguments)) { |
| 7239 return this; |
| 7240 } |
| 7241 InterfaceTypeImpl newType = new InterfaceTypeImpl.con1(element); |
| 7242 newType.typeArguments = newTypeArguments; |
| 7243 return newType; |
| 7244 } |
| 7245 |
| 7246 @override |
| 7247 void appendTo(JavaStringBuilder builder) { |
| 7248 builder.append(name); |
| 7249 int argumentCount = typeArguments.length; |
| 7250 if (argumentCount > 0) { |
| 7251 builder.append("<"); |
| 7252 for (int i = 0; i < argumentCount; i++) { |
| 7253 if (i > 0) { |
| 7254 builder.append(", "); |
| 7255 } |
| 7256 (typeArguments[i] as TypeImpl).appendTo(builder); |
| 7257 } |
| 7258 builder.append(">"); |
| 7259 } |
| 7260 } |
| 7261 |
| 7262 @override |
| 7263 bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) { |
| 7264 if (object is! InterfaceTypeImpl) { |
| 7265 return false; |
| 7266 } |
| 7267 InterfaceTypeImpl otherType = object as InterfaceTypeImpl; |
| 7268 return (element == otherType.element) && TypeImpl.equalArrays(typeArguments,
otherType.typeArguments, visitedElementPairs); |
| 7269 } |
| 7270 |
| 7271 @override |
| 7272 bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_
TypePair> visitedTypePairs) { |
| 7273 // |
| 7274 // S is dynamic. |
| 7275 // The test to determine whether S is dynamic is done here because dynamic i
s not an instance of |
| 7276 // InterfaceType. |
| 7277 // |
| 7278 if (identical(type, DynamicTypeImpl.instance)) { |
| 7279 return true; |
| 7280 } else if (type is UnionType) { |
| 7281 return (type as UnionTypeImpl).internalUnionTypeIsMoreSpecificThan(this, w
ithDynamic, visitedTypePairs); |
| 7282 } else if (type is! InterfaceType) { |
| 7283 return false; |
| 7284 } |
| 7285 return _isMoreSpecificThan(type as InterfaceType, new HashSet<ClassElement>(
), withDynamic, visitedTypePairs); |
| 7286 } |
| 7287 |
| 7288 @override |
| 7289 bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePair
s) { |
| 7290 // |
| 7291 // T is a subtype of S, written T <: S, iff [bottom/dynamic]T << S |
| 7292 // |
| 7293 if (type.isDynamic) { |
| 7294 return true; |
| 7295 } else if (type is TypeParameterType) { |
| 7296 return false; |
| 7297 } else if (type is UnionType) { |
| 7298 return (type as UnionTypeImpl).internalUnionTypeIsSuperTypeOf(this, visite
dTypePairs); |
| 7299 } else if (type is FunctionType) { |
| 7300 // This implementation assumes transitivity |
| 7301 // for function type subtyping on the RHS, but a literal reading |
| 7302 // of the spec does not specify this. More precisely: if T <: F1 and F1 <:
F2 and |
| 7303 // F1 and F2 are function types, then we assume T <: F2. |
| 7304 // |
| 7305 // From the Function Types section of the spec: |
| 7306 // |
| 7307 // If a type I includes an instance method named call(), and the type of
call() |
| 7308 // is the function type F, then I is considered to be a subtype of F. |
| 7309 // |
| 7310 // However, the section on Interface Types says |
| 7311 // |
| 7312 // T is a subtype of S, written T <: S, iff [bottom/dynamic]T << S. |
| 7313 // |
| 7314 // after giving rules for << (pronounced "more specific than"). However, t
he "only if" |
| 7315 // direction of the "iff" |
| 7316 // in the definition of <: seems to be contradicted by the special case <:
rule |
| 7317 // quoted from the Function Types section: I see no rule for << which tell
s us that |
| 7318 // I << F if I has call() at type F. |
| 7319 // |
| 7320 // After defining <: , the spec then |
| 7321 // emphasizes that unlike the relation <<, the relation <: is not transiti
ve in general: |
| 7322 // |
| 7323 // Note that <: is not a partial order on types, it is only binary relat
ion on types. |
| 7324 // This is because <: is not transitive. If it was, the subtype rule wou
ld have a cycle. |
| 7325 // For example: List <: List<String> and List<int> <: List, but List<int
> is not a subtype |
| 7326 // of List<String>. Although <: is not a partial order on types, it does
contain a partial |
| 7327 // order, namely <<. This means that, barring raw types, intuition about
classical subtype |
| 7328 // rules does apply. |
| 7329 // |
| 7330 // There is no other occurrence of the word "raw" in relation to types in
the spec that I can |
| 7331 // find, but presumably it's a reference to |
| 7332 // |
| 7333 // http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html |
| 7334 // |
| 7335 // so e.g. non-generic types are never raw. As pointed out by paulberry, i
t's not clear |
| 7336 // whether a type like T<int, dynamic> should be considered raw or not. On
the one hand, it |
| 7337 // doesn't correspond to a "raw"-in-the-Java-sense occurrence of T, which
would instead |
| 7338 // be T<dynamic, dynamic>; on the other hand, it's treated differently by
<: and << when |
| 7339 // occurring on the left hand side. |
| 7340 ClassElement element = this.element; |
| 7341 InheritanceManager manager = new InheritanceManager(element.library); |
| 7342 FunctionType callType = manager.lookupMemberType(this, "call"); |
| 7343 if (callType != null) { |
| 7344 // A more literal reading of the spec would give something like |
| 7345 // |
| 7346 // return callType.equals(type) |
| 7347 // |
| 7348 // here, but that causes 101 errors in the external tests |
| 7349 // (tools/test.py --mode release --compiler dartanalyzer --runtime none)
. |
| 7350 return callType.isSubtypeOf(type); |
| 7351 } |
| 7352 return false; |
| 7353 } else if (type is! InterfaceType) { |
| 7354 return false; |
| 7355 } else if (this == type) { |
| 7356 return true; |
| 7357 } |
| 7358 return _isSubtypeOf(type as InterfaceType, new HashSet<ClassElement>(), visi
tedTypePairs); |
| 7359 } |
| 7360 |
| 7361 bool _isMoreSpecificThan(InterfaceType s, HashSet<ClassElement> visitedClasses
, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) { |
| 7362 // |
| 7363 // A type T is more specific than a type S, written T << S, if one of the f
ollowing conditions |
| 7364 // is met: |
| 7365 // |
| 7366 // Reflexivity: T is S. |
| 7367 // |
| 7368 if (this == s) { |
| 7369 return true; |
| 7370 } |
| 7371 // |
| 7372 // T is bottom. (This case is handled by the class BottomTypeImpl.) |
| 7373 // |
| 7374 // Direct supertype: S is a direct supertype of T. |
| 7375 // |
| 7376 if (s.isDirectSupertypeOf(this)) { |
| 7377 return true; |
| 7378 } |
| 7379 // |
| 7380 // Covariance: T is of the form I<T1, ..., Tn> and S is of the form I<S1, ..
., Sn> and Ti << Si, 1 <= i <= n. |
| 7381 // |
| 7382 ClassElement tElement = this.element; |
| 7383 ClassElement sElement = s.element; |
| 7384 if (tElement == sElement) { |
| 7385 List<DartType> tArguments = typeArguments; |
| 7386 List<DartType> sArguments = s.typeArguments; |
| 7387 if (tArguments.length != sArguments.length) { |
| 7388 return false; |
| 7389 } |
| 7390 for (int i = 0; i < tArguments.length; i++) { |
| 7391 if (!(tArguments[i] as TypeImpl).isMoreSpecificThan2(sArguments[i], with
Dynamic, visitedTypePairs)) { |
| 7392 return false; |
| 7393 } |
| 7394 } |
| 7395 return true; |
| 7396 } |
| 7397 // |
| 7398 // Transitivity: T << U and U << S. |
| 7399 // |
| 7400 // First check for infinite loops |
| 7401 ClassElement element = this.element; |
| 7402 if (element == null || visitedClasses.contains(element)) { |
| 7403 return false; |
| 7404 } |
| 7405 visitedClasses.add(element); |
| 7406 // Iterate over all of the types U that are more specific than T because the
y are direct |
| 7407 // supertypes of T and return true if any of them are more specific than S. |
| 7408 InterfaceType supertype = superclass; |
| 7409 if (supertype != null && (supertype as InterfaceTypeImpl)._isMoreSpecificTha
n(s, visitedClasses, withDynamic, visitedTypePairs)) { |
| 7410 return true; |
| 7411 } |
| 7412 for (InterfaceType interfaceType in interfaces) { |
| 7413 if ((interfaceType as InterfaceTypeImpl)._isMoreSpecificThan(s, visitedCla
sses, withDynamic, visitedTypePairs)) { |
| 7414 return true; |
| 7415 } |
| 7416 } |
| 7417 for (InterfaceType mixinType in mixins) { |
| 7418 if ((mixinType as InterfaceTypeImpl)._isMoreSpecificThan(s, visitedClasses
, withDynamic, visitedTypePairs)) { |
| 7419 return true; |
| 7420 } |
| 7421 } |
| 7422 return false; |
| 7423 } |
| 7424 |
| 7425 bool _isSubtypeOf(InterfaceType type, HashSet<ClassElement> visitedClasses, Se
t<TypeImpl_TypePair> visitedTypePairs) { |
| 7426 InterfaceType typeT = this; |
| 7427 InterfaceType typeS = type; |
| 7428 ClassElement elementT = element; |
| 7429 if (elementT == null || visitedClasses.contains(elementT)) { |
| 7430 return false; |
| 7431 } |
| 7432 visitedClasses.add(elementT); |
| 7433 if (typeT == typeS) { |
| 7434 return true; |
| 7435 } else if (elementT == typeS.element) { |
| 7436 // For each of the type arguments return true if all type args from T is a
subtype of all |
| 7437 // types from S. |
| 7438 List<DartType> typeTArgs = typeT.typeArguments; |
| 7439 List<DartType> typeSArgs = typeS.typeArguments; |
| 7440 if (typeTArgs.length != typeSArgs.length) { |
| 7441 // This case covers the case where two objects are being compared that h
ave a different |
| 7442 // number of parameterized types. |
| 7443 return false; |
| 7444 } |
| 7445 for (int i = 0; i < typeTArgs.length; i++) { |
| 7446 // Recursively call isSubtypeOf the type arguments and return false if t
he T argument is not |
| 7447 // a subtype of the S argument. |
| 7448 if (!(typeTArgs[i] as TypeImpl).isSubtypeOf2(typeSArgs[i], visitedTypePa
irs)) { |
| 7449 return false; |
| 7450 } |
| 7451 } |
| 7452 return true; |
| 7453 } else if (typeS.isDartCoreFunction && elementT.getMethod("call") != null) { |
| 7454 return true; |
| 7455 } |
| 7456 InterfaceType supertype = superclass; |
| 7457 // The type is Object, return false. |
| 7458 if (supertype != null && (supertype as InterfaceTypeImpl)._isSubtypeOf(typeS
, visitedClasses, visitedTypePairs)) { |
| 7459 return true; |
| 7460 } |
| 7461 List<InterfaceType> interfaceTypes = interfaces; |
| 7462 for (InterfaceType interfaceType in interfaceTypes) { |
| 7463 if ((interfaceType as InterfaceTypeImpl)._isSubtypeOf(typeS, visitedClasse
s, visitedTypePairs)) { |
| 7464 return true; |
| 7465 } |
| 7466 } |
| 7467 List<InterfaceType> mixinTypes = mixins; |
| 7468 for (InterfaceType mixinType in mixinTypes) { |
| 7469 if ((mixinType as InterfaceTypeImpl)._isSubtypeOf(typeS, visitedClasses, v
isitedTypePairs)) { |
| 7470 return true; |
| 7471 } |
| 7472 } |
| 7473 return false; |
| 7474 } |
| 7475 } |
| 7476 |
| 7477 /** |
| 7478 * Combination of [AngularTagSelectorElementImpl] and [HasAttributeSelectorEleme
ntImpl]. |
| 7479 */ |
| 7480 class IsTagHasAttributeSelectorElementImpl extends AngularSelectorElementImpl { |
| 7481 String _tagName; |
| 7482 |
| 7483 String _attributeName; |
| 7484 |
| 7485 IsTagHasAttributeSelectorElementImpl(String tagName, String attributeName) : s
uper("${tagName}[${attributeName}]", -1) { |
| 7486 this._tagName = tagName; |
| 7487 this._attributeName = attributeName; |
| 7488 } |
| 7489 |
| 7490 @override |
| 7491 bool apply(XmlTagNode node) => node.tag == _tagName && node.getAttribute(_attr
ibuteName) != null; |
| 7492 |
| 7493 String get attributeName => _attributeName; |
| 7494 |
| 7495 String get tagName => _tagName; |
| 7496 } |
| 7497 |
| 7498 /** |
| 7499 * The interface `LabelElement` defines the behavior of elements representing a
label |
| 7500 * associated with a statement. |
| 7501 */ |
| 7502 abstract class LabelElement implements Element { |
| 7503 /** |
| 7504 * Return the executable element in which this label is defined. |
| 7505 * |
| 7506 * @return the executable element in which this label is defined |
| 7507 */ |
| 7508 @override |
| 7509 ExecutableElement get enclosingElement; |
| 7510 } |
| 7511 |
| 7512 /** |
| 7513 * Instances of the class `LabelElementImpl` implement a `LabelElement`. |
| 7514 */ |
| 7515 class LabelElementImpl extends ElementImpl implements LabelElement { |
| 7516 /** |
| 7517 * A flag indicating whether this label is associated with a `switch` statemen
t. |
| 7518 */ |
| 7519 final bool _onSwitchStatement; |
| 7520 |
| 7521 /** |
| 7522 * A flag indicating whether this label is associated with a `switch` member (
`case` |
| 7523 * or `default`). |
| 7524 */ |
| 7525 final bool _onSwitchMember; |
| 7526 |
| 7527 /** |
| 7528 * An empty array of label elements. |
| 7529 */ |
| 7530 static List<LabelElement> EMPTY_ARRAY = new List<LabelElement>(0); |
| 7531 |
| 7532 /** |
| 7533 * Initialize a newly created label element to have the given name. |
| 7534 * |
| 7535 * @param name the name of this element |
| 7536 * @param onSwitchStatement `true` if this label is associated with a `switch` |
| 7537 * statement |
| 7538 * @param onSwitchMember `true` if this label is associated with a `switch` me
mber |
| 7539 */ |
| 7540 LabelElementImpl(Identifier name, this._onSwitchStatement, this._onSwitchMembe
r) : super.forNode(name); |
| 7541 |
| 7542 @override |
| 7543 accept(ElementVisitor visitor) => visitor.visitLabelElement(this); |
| 7544 |
| 7545 @override |
| 7546 ExecutableElement get enclosingElement => super.enclosingElement as Executable
Element; |
| 7547 |
| 7548 @override |
| 7549 ElementKind get kind => ElementKind.LABEL; |
| 7550 |
| 7551 /** |
| 7552 * Return `true` if this label is associated with a `switch` member (`case` or |
| 7553 * `default`). |
| 7554 * |
| 7555 * @return `true` if this label is associated with a `switch` member |
| 7556 */ |
| 7557 bool get isOnSwitchMember => _onSwitchMember; |
| 7558 |
| 7559 /** |
| 7560 * Return `true` if this label is associated with a `switch` statement. |
| 7561 * |
| 7562 * @return `true` if this label is associated with a `switch` statement |
| 7563 */ |
| 7564 bool get isOnSwitchStatement => _onSwitchStatement; |
| 7565 } |
| 7566 |
| 7567 /** |
| 7568 * The interface `LibraryElement` defines the behavior of elements representing
a library. |
| 7569 */ |
| 7570 abstract class LibraryElement implements Element { |
| 7571 /** |
| 7572 * Return the compilation unit that defines this library. |
| 7573 * |
| 7574 * @return the compilation unit that defines this library |
| 7575 */ |
| 7576 CompilationUnitElement get definingCompilationUnit; |
| 7577 |
| 7578 /** |
| 7579 * Return the entry point for this library, or `null` if this library does not
have an entry |
| 7580 * point. The entry point is defined to be a zero argument top-level function
whose name is |
| 7581 * `main`. |
| 7582 * |
| 7583 * @return the entry point for this library |
| 7584 */ |
| 7585 FunctionElement get entryPoint; |
| 7586 |
| 7587 /** |
| 7588 * Return an array containing all of the libraries that are exported from this
library. |
| 7589 * |
| 7590 * @return an array containing all of the libraries that are exported from thi
s library |
| 7591 */ |
| 7592 List<LibraryElement> get exportedLibraries; |
| 7593 |
| 7594 /** |
| 7595 * Return an array containing all of the exports defined in this library. |
| 7596 * |
| 7597 * @return the exports defined in this library |
| 7598 */ |
| 7599 List<ExportElement> get exports; |
| 7600 |
| 7601 /** |
| 7602 * Return an array containing all of the libraries that are imported into this
library. This |
| 7603 * includes all of the libraries that are imported using a prefix (also availa
ble through the |
| 7604 * prefixes returned by [getPrefixes]) and those that are imported without a p
refix. |
| 7605 * |
| 7606 * @return an array containing all of the libraries that are imported into thi
s library |
| 7607 */ |
| 7608 List<LibraryElement> get importedLibraries; |
| 7609 |
| 7610 /** |
| 7611 * Return an array containing all of the imports defined in this library. |
| 7612 * |
| 7613 * @return the imports defined in this library |
| 7614 */ |
| 7615 List<ImportElement> get imports; |
| 7616 |
| 7617 /** |
| 7618 * Return an array containing all of the imports that share the given prefix,
or an empty array if |
| 7619 * there are no such imports. |
| 7620 * |
| 7621 * @param prefixElement the prefix element shared by the returned imports |
| 7622 */ |
| 7623 List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement); |
| 7624 |
| 7625 /** |
| 7626 * Return the element representing the synthetic function `loadLibrary` that i
s implicitly |
| 7627 * defined for this library if the library is imported using a deferred import
. |
| 7628 */ |
| 7629 FunctionElement get loadLibraryFunction; |
| 7630 |
| 7631 /** |
| 7632 * Return an array containing all of the compilation units that are included i
n this library using |
| 7633 * a `part` directive. This does not include the defining compilation unit tha
t contains the |
| 7634 * `part` directives. |
| 7635 * |
| 7636 * @return the compilation units that are included in this library |
| 7637 */ |
| 7638 List<CompilationUnitElement> get parts; |
| 7639 |
| 7640 /** |
| 7641 * Return an array containing elements for each of the prefixes used to `impor
t` libraries |
| 7642 * into this library. Each prefix can be used in more than one `import` direct
ive. |
| 7643 * |
| 7644 * @return the prefixes used to `import` libraries into this library |
| 7645 */ |
| 7646 List<PrefixElement> get prefixes; |
| 7647 |
| 7648 /** |
| 7649 * Return the class defined in this library that has the given name, or `null`
if this |
| 7650 * library does not define a class with the given name. |
| 7651 * |
| 7652 * @param className the name of the class to be returned |
| 7653 * @return the class with the given name that is defined in this library |
| 7654 */ |
| 7655 ClassElement getType(String className); |
| 7656 |
| 7657 /** |
| 7658 * Return an array containing all of the compilation units this library consis
ts of. This includes |
| 7659 * the defining compilation unit and units included using the `part` directive
. |
| 7660 * |
| 7661 * @return the compilation units this library consists of |
| 7662 */ |
| 7663 List<CompilationUnitElement> get units; |
| 7664 |
| 7665 /** |
| 7666 * Return an array containing all directly and indirectly imported libraries. |
| 7667 * |
| 7668 * @return all directly and indirectly imported libraries |
| 7669 */ |
| 7670 List<LibraryElement> get visibleLibraries; |
| 7671 |
| 7672 /** |
| 7673 * Return `true` if the defining compilation unit of this library contains at
least one |
| 7674 * import directive whose URI uses the "dart-ext" scheme. |
| 7675 */ |
| 7676 bool get hasExtUri; |
| 7677 |
| 7678 /** |
| 7679 * Return `true` if this library defines a top-level function named `loadLibra
ry`. |
| 7680 * |
| 7681 * @return `true` if this library defines a top-level function named `loadLibr
ary` |
| 7682 */ |
| 7683 bool get hasLoadLibraryFunction; |
| 7684 |
| 7685 /** |
| 7686 * Return `true` if this library is created for Angular analysis. If this libr
ary has not |
| 7687 * yet had toolkit references resolved, then `false` will be returned. |
| 7688 * |
| 7689 * @return `true` if this library is created for Angular analysis |
| 7690 */ |
| 7691 bool get isAngularHtml; |
| 7692 |
| 7693 /** |
| 7694 * Return `true` if this library is an application that can be run in the brow
ser. |
| 7695 * |
| 7696 * @return `true` if this library is an application that can be run in the bro
wser |
| 7697 */ |
| 7698 bool get isBrowserApplication; |
| 7699 |
| 7700 /** |
| 7701 * Return `true` if this library is the dart:core library. |
| 7702 * |
| 7703 * @return `true` if this library is the dart:core library |
| 7704 */ |
| 7705 bool get isDartCore; |
| 7706 |
| 7707 /** |
| 7708 * Return `true` if this library is the dart:core library. |
| 7709 * |
| 7710 * @return `true` if this library is the dart:core library |
| 7711 */ |
| 7712 bool get isInSdk; |
| 7713 |
| 7714 /** |
| 7715 * Return `true` if this library is up to date with respect to the given time
stamp. If any |
| 7716 * transitively referenced Source is newer than the time stamp, this method re
turns false. |
| 7717 * |
| 7718 * @param timeStamp the time stamp to compare against |
| 7719 * @return `true` if this library is up to date with respect to the given time
stamp |
| 7720 */ |
| 7721 bool isUpToDate(int timeStamp); |
| 7722 } |
| 7723 |
| 7724 /** |
| 7725 * Instances of the class `LibraryElementImpl` implement a `LibraryElement`. |
| 7726 */ |
| 7727 class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| 7728 /** |
| 7729 * An empty array of library elements. |
| 7730 */ |
| 7731 static List<LibraryElement> EMPTY_ARRAY = new List<LibraryElement>(0); |
| 7732 |
| 7733 /** |
| 7734 * Determine if the given library is up to date with respect to the given time
stamp. |
| 7735 * |
| 7736 * @param library the library to process |
| 7737 * @param timeStamp the time stamp to check against |
| 7738 * @param visitedLibraries the set of visited libraries |
| 7739 */ |
| 7740 static bool _safeIsUpToDate(LibraryElement library, int timeStamp, Set<Library
Element> visitedLibraries) { |
| 7741 if (!visitedLibraries.contains(library)) { |
| 7742 visitedLibraries.add(library); |
| 7743 AnalysisContext context = library.context; |
| 7744 // Check the defining compilation unit. |
| 7745 if (timeStamp < context.getModificationStamp(library.definingCompilationUn
it.source)) { |
| 7746 return false; |
| 7747 } |
| 7748 // Check the parted compilation units. |
| 7749 for (CompilationUnitElement element in library.parts) { |
| 7750 if (timeStamp < context.getModificationStamp(element.source)) { |
| 7751 return false; |
| 7752 } |
| 7753 } |
| 7754 // Check the imported libraries. |
| 7755 for (LibraryElement importedLibrary in library.importedLibraries) { |
| 7756 if (!_safeIsUpToDate(importedLibrary, timeStamp, visitedLibraries)) { |
| 7757 return false; |
| 7758 } |
| 7759 } |
| 7760 // Check the exported libraries. |
| 7761 for (LibraryElement exportedLibrary in library.exportedLibraries) { |
| 7762 if (!_safeIsUpToDate(exportedLibrary, timeStamp, visitedLibraries)) { |
| 7763 return false; |
| 7764 } |
| 7765 } |
| 7766 } |
| 7767 return true; |
| 7768 } |
| 7769 |
| 7770 /** |
| 7771 * The analysis context in which this library is defined. |
| 7772 */ |
| 7773 final AnalysisContext context; |
| 7774 |
| 7775 /** |
| 7776 * The compilation unit that defines this library. |
| 7777 */ |
| 7778 CompilationUnitElement _definingCompilationUnit; |
| 7779 |
| 7780 /** |
| 7781 * The entry point for this library, or `null` if this library does not have a
n entry point. |
| 7782 */ |
| 7783 FunctionElement entryPoint; |
| 7784 |
| 7785 /** |
| 7786 * An array containing specifications of all of the imports defined in this li
brary. |
| 7787 */ |
| 7788 List<ImportElement> _imports = ImportElement.EMPTY_ARRAY; |
| 7789 |
| 7790 /** |
| 7791 * An array containing specifications of all of the exports defined in this li
brary. |
| 7792 */ |
| 7793 List<ExportElement> _exports = ExportElement.EMPTY_ARRAY; |
| 7794 |
| 7795 /** |
| 7796 * An array containing all of the compilation units that are included in this
library using a |
| 7797 * `part` directive. |
| 7798 */ |
| 7799 List<CompilationUnitElement> _parts = CompilationUnitElementImpl.EMPTY_ARRAY; |
| 7800 |
| 7801 /** |
| 7802 * Is `true` if this library is created for Angular analysis. |
| 7803 */ |
| 7804 bool _isAngularHtml = false; |
| 7805 |
| 7806 /** |
| 7807 * The element representing the synthetic function `loadLibrary` that is defin
ed for this |
| 7808 * library, or `null` if the element has not yet been created. |
| 7809 */ |
| 7810 FunctionElement _loadLibraryFunction; |
| 7811 |
| 7812 /** |
| 7813 * Initialize a newly created library element to have the given name. |
| 7814 * |
| 7815 * @param context the analysis context in which the library is defined |
| 7816 * @param name the name of this element |
| 7817 */ |
| 7818 LibraryElementImpl.forNode(this.context, LibraryIdentifier name) : super.forNo
de(name); |
| 7819 |
| 7820 /** |
| 7821 * Initialize a newly created library element to have the given name. |
| 7822 * |
| 7823 * @param context the analysis context in which the library is defined |
| 7824 * @param name the name of this element |
| 7825 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 7826 * declaration of this element |
| 7827 */ |
| 7828 LibraryElementImpl(this.context, String name, int nameOffset) : super(name, na
meOffset); |
| 7829 |
| 7830 @override |
| 7831 accept(ElementVisitor visitor) => visitor.visitLibraryElement(this); |
| 7832 |
| 7833 @override |
| 7834 bool operator ==(Object object) => object != null && runtimeType == object.run
timeType && _definingCompilationUnit == (object as LibraryElementImpl).definingC
ompilationUnit; |
| 7835 |
| 7836 @override |
| 7837 ElementImpl getChild(String identifier) { |
| 7838 if ((_definingCompilationUnit as CompilationUnitElementImpl).identifier == i
dentifier) { |
| 7839 return _definingCompilationUnit as CompilationUnitElementImpl; |
| 7840 } |
| 7841 for (CompilationUnitElement part in _parts) { |
| 7842 if ((part as CompilationUnitElementImpl).identifier == identifier) { |
| 7843 return part as CompilationUnitElementImpl; |
| 7844 } |
| 7845 } |
| 7846 for (ImportElement importElement in _imports) { |
| 7847 if ((importElement as ImportElementImpl).identifier == identifier) { |
| 7848 return importElement as ImportElementImpl; |
| 7849 } |
| 7850 } |
| 7851 for (ExportElement exportElement in _exports) { |
| 7852 if ((exportElement as ExportElementImpl).identifier == identifier) { |
| 7853 return exportElement as ExportElementImpl; |
| 7854 } |
| 7855 } |
| 7856 return null; |
| 7857 } |
| 7858 |
| 7859 @override |
| 7860 CompilationUnitElement get definingCompilationUnit => _definingCompilationUnit
; |
| 7861 |
| 7862 @override |
| 7863 List<LibraryElement> get exportedLibraries { |
| 7864 HashSet<LibraryElement> libraries = new HashSet<LibraryElement>(); |
| 7865 for (ExportElement element in _exports) { |
| 7866 LibraryElement library = element.exportedLibrary; |
| 7867 if (library != null) { |
| 7868 libraries.add(library); |
| 7869 } |
| 7870 } |
| 7871 return new List.from(libraries); |
| 7872 } |
| 7873 |
| 7874 @override |
| 7875 List<ExportElement> get exports => _exports; |
| 7876 |
| 7877 @override |
| 7878 List<LibraryElement> get importedLibraries { |
| 7879 HashSet<LibraryElement> libraries = new HashSet<LibraryElement>(); |
| 7880 for (ImportElement element in _imports) { |
| 7881 LibraryElement library = element.importedLibrary; |
| 7882 if (library != null) { |
| 7883 libraries.add(library); |
| 7884 } |
| 7885 } |
| 7886 return new List.from(libraries); |
| 7887 } |
| 7888 |
| 7889 @override |
| 7890 List<ImportElement> get imports => _imports; |
| 7891 |
| 7892 @override |
| 7893 List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) { |
| 7894 int count = _imports.length; |
| 7895 List<ImportElement> importList = new List<ImportElement>(); |
| 7896 for (int i = 0; i < count; i++) { |
| 7897 if (identical(_imports[i].prefix, prefixElement)) { |
| 7898 importList.add(_imports[i]); |
| 7899 } |
| 7900 } |
| 7901 return new List.from(importList); |
| 7902 } |
| 7903 |
| 7904 @override |
| 7905 ElementKind get kind => ElementKind.LIBRARY; |
| 7906 |
| 7907 @override |
| 7908 LibraryElement get library => this; |
| 7909 |
| 7910 @override |
| 7911 FunctionElement get loadLibraryFunction { |
| 7912 if (_loadLibraryFunction == null) { |
| 7913 FunctionElementImpl function = new FunctionElementImpl(FunctionElement.LOA
D_LIBRARY_NAME, -1); |
| 7914 function.synthetic = true; |
| 7915 function.enclosingElement = this; |
| 7916 function.returnType = loadLibraryReturnType; |
| 7917 function.type = new FunctionTypeImpl.con1(function); |
| 7918 _loadLibraryFunction = function; |
| 7919 } |
| 7920 return _loadLibraryFunction; |
| 7921 } |
| 7922 |
| 7923 @override |
| 7924 List<CompilationUnitElement> get parts => _parts; |
| 7925 |
| 7926 @override |
| 7927 List<PrefixElement> get prefixes { |
| 7928 HashSet<PrefixElement> prefixes = new HashSet<PrefixElement>(); |
| 7929 for (ImportElement element in _imports) { |
| 7930 PrefixElement prefix = element.prefix; |
| 7931 if (prefix != null) { |
| 7932 prefixes.add(prefix); |
| 7933 } |
| 7934 } |
| 7935 return new List.from(prefixes); |
| 7936 } |
| 7937 |
| 7938 @override |
| 7939 Source get source { |
| 7940 if (_definingCompilationUnit == null) { |
| 7941 return null; |
| 7942 } |
| 7943 return _definingCompilationUnit.source; |
| 7944 } |
| 7945 |
| 7946 @override |
| 7947 ClassElement getType(String className) { |
| 7948 ClassElement type = _definingCompilationUnit.getType(className); |
| 7949 if (type != null) { |
| 7950 return type; |
| 7951 } |
| 7952 for (CompilationUnitElement part in _parts) { |
| 7953 type = part.getType(className); |
| 7954 if (type != null) { |
| 7955 return type; |
| 7956 } |
| 7957 } |
| 7958 return null; |
| 7959 } |
| 7960 |
| 7961 @override |
| 7962 List<CompilationUnitElement> get units { |
| 7963 List<CompilationUnitElement> units = new List<CompilationUnitElement>(1 + _p
arts.length); |
| 7964 units[0] = _definingCompilationUnit; |
| 7965 JavaSystem.arraycopy(_parts, 0, units, 1, _parts.length); |
| 7966 return units; |
| 7967 } |
| 7968 |
| 7969 @override |
| 7970 List<LibraryElement> get visibleLibraries { |
| 7971 Set<LibraryElement> visibleLibraries = new Set(); |
| 7972 _addVisibleLibraries(visibleLibraries, false); |
| 7973 return new List.from(visibleLibraries); |
| 7974 } |
| 7975 |
| 7976 @override |
| 7977 bool get hasExtUri => hasModifier(Modifier.HAS_EXT_URI); |
| 7978 |
| 7979 @override |
| 7980 int get hashCode => _definingCompilationUnit.hashCode; |
| 7981 |
| 7982 @override |
| 7983 bool get hasLoadLibraryFunction { |
| 7984 if (_definingCompilationUnit.hasLoadLibraryFunction) { |
| 7985 return true; |
| 7986 } |
| 7987 for (int i = 0; i < _parts.length; i++) { |
| 7988 if (_parts[i].hasLoadLibraryFunction) { |
| 7989 return true; |
| 7990 } |
| 7991 } |
| 7992 return false; |
| 7993 } |
| 7994 |
| 7995 @override |
| 7996 bool get isAngularHtml => _isAngularHtml; |
| 7997 |
| 7998 @override |
| 7999 bool get isBrowserApplication => entryPoint != null && isOrImportsBrowserLibra
ry; |
| 8000 |
| 8001 @override |
| 8002 bool get isDartCore => name == "dart.core"; |
| 8003 |
| 8004 @override |
| 8005 bool get isInSdk => StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x7
4, 0x2E); |
| 8006 |
| 8007 @override |
| 8008 bool isUpToDate(int timeStamp) { |
| 8009 Set<LibraryElement> visitedLibraries = new Set(); |
| 8010 return _safeIsUpToDate(this, timeStamp, visitedLibraries); |
| 8011 } |
| 8012 |
| 8013 /** |
| 8014 * Specifies if this library is created for Angular analysis. |
| 8015 */ |
| 8016 void set angularHtml(bool isAngularHtml) { |
| 8017 this._isAngularHtml = isAngularHtml; |
| 8018 } |
| 8019 |
| 8020 /** |
| 8021 * Set the compilation unit that defines this library to the given compilation
unit. |
| 8022 * |
| 8023 * @param definingCompilationUnit the compilation unit that defines this libra
ry |
| 8024 */ |
| 8025 void set definingCompilationUnit(CompilationUnitElement definingCompilationUni
t) { |
| 8026 (definingCompilationUnit as CompilationUnitElementImpl).enclosingElement = t
his; |
| 8027 this._definingCompilationUnit = definingCompilationUnit; |
| 8028 } |
| 8029 |
| 8030 /** |
| 8031 * Set the specifications of all of the exports defined in this library to the
given array. |
| 8032 * |
| 8033 * @param exports the specifications of all of the exports defined in this lib
rary |
| 8034 */ |
| 8035 void set exports(List<ExportElement> exports) { |
| 8036 for (ExportElement exportElement in exports) { |
| 8037 (exportElement as ExportElementImpl).enclosingElement = this; |
| 8038 } |
| 8039 this._exports = exports; |
| 8040 } |
| 8041 |
| 8042 /** |
| 8043 * Set whether this library has an import of a "dart-ext" URI to the given val
ue. |
| 8044 * |
| 8045 * @param hasExtUri `true` if this library has an import of a "dart-ext" URI |
| 8046 */ |
| 8047 void set hasExtUri(bool hasExtUri) { |
| 8048 setModifier(Modifier.HAS_EXT_URI, hasExtUri); |
| 8049 } |
| 8050 |
| 8051 /** |
| 8052 * Set the specifications of all of the imports defined in this library to the
given array. |
| 8053 * |
| 8054 * @param imports the specifications of all of the imports defined in this lib
rary |
| 8055 */ |
| 8056 void set imports(List<ImportElement> imports) { |
| 8057 for (ImportElement importElement in imports) { |
| 8058 (importElement as ImportElementImpl).enclosingElement = this; |
| 8059 PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl; |
| 8060 if (prefix != null) { |
| 8061 prefix.enclosingElement = this; |
| 8062 } |
| 8063 } |
| 8064 this._imports = imports; |
| 8065 } |
| 8066 |
| 8067 /** |
| 8068 * Set the compilation units that are included in this library using a `part`
directive. |
| 8069 * |
| 8070 * @param parts the compilation units that are included in this library using
a `part` |
| 8071 * directive |
| 8072 */ |
| 8073 void set parts(List<CompilationUnitElement> parts) { |
| 8074 for (CompilationUnitElement compilationUnit in parts) { |
| 8075 (compilationUnit as CompilationUnitElementImpl).enclosingElement = this; |
| 8076 } |
| 8077 this._parts = parts; |
| 8078 } |
| 8079 |
| 8080 @override |
| 8081 void visitChildren(ElementVisitor visitor) { |
| 8082 super.visitChildren(visitor); |
| 8083 safelyVisitChild(_definingCompilationUnit, visitor); |
| 8084 safelyVisitChildren(_exports, visitor); |
| 8085 safelyVisitChildren(_imports, visitor); |
| 8086 safelyVisitChildren(_parts, visitor); |
| 8087 } |
| 8088 |
| 8089 @override |
| 8090 String get identifier => _definingCompilationUnit.source.encoding; |
| 8091 |
| 8092 /** |
| 8093 * Recursively fills set of visible libraries for [getVisibleElementsLibraries
]. |
| 8094 */ |
| 8095 void _addVisibleLibraries(Set<LibraryElement> visibleLibraries, bool includeEx
ports) { |
| 8096 // maybe already processed |
| 8097 if (!visibleLibraries.add(this)) { |
| 8098 return; |
| 8099 } |
| 8100 // add imported libraries |
| 8101 for (ImportElement importElement in _imports) { |
| 8102 LibraryElement importedLibrary = importElement.importedLibrary; |
| 8103 if (importedLibrary != null) { |
| 8104 (importedLibrary as LibraryElementImpl)._addVisibleLibraries(visibleLibr
aries, true); |
| 8105 } |
| 8106 } |
| 8107 // add exported libraries |
| 8108 if (includeExports) { |
| 8109 for (ExportElement exportElement in _exports) { |
| 8110 LibraryElement exportedLibrary = exportElement.exportedLibrary; |
| 8111 if (exportedLibrary != null) { |
| 8112 (exportedLibrary as LibraryElementImpl)._addVisibleLibraries(visibleLi
braries, true); |
| 8113 } |
| 8114 } |
| 8115 } |
| 8116 } |
| 8117 |
| 8118 /** |
| 8119 * Return the object representing the type "Future" from the dart:async librar
y, or the type |
| 8120 * "void" if the type "Future" cannot be accessed. |
| 8121 * |
| 8122 * @return the type "Future" from the dart:async library |
| 8123 */ |
| 8124 DartType get loadLibraryReturnType { |
| 8125 try { |
| 8126 Source asyncSource = context.sourceFactory.forUri(DartSdk.DART_ASYNC); |
| 8127 if (asyncSource == null) { |
| 8128 AnalysisEngine.instance.logger.logError("Could not create a source for d
art:async"); |
| 8129 return VoidTypeImpl.instance; |
| 8130 } |
| 8131 LibraryElement asyncElement = context.computeLibraryElement(asyncSource); |
| 8132 if (asyncElement == null) { |
| 8133 AnalysisEngine.instance.logger.logError("Could not build the element mod
el for dart:async"); |
| 8134 return VoidTypeImpl.instance; |
| 8135 } |
| 8136 ClassElement futureElement = asyncElement.getType("Future"); |
| 8137 if (futureElement == null) { |
| 8138 AnalysisEngine.instance.logger.logError("Could not find type Future in d
art:async"); |
| 8139 return VoidTypeImpl.instance; |
| 8140 } |
| 8141 InterfaceType futureType = futureElement.type; |
| 8142 return futureType.substitute4(<DartType> [DynamicTypeImpl.instance]); |
| 8143 } on AnalysisException catch (exception, stackTrace) { |
| 8144 AnalysisEngine.instance.logger.logError2("Could not build the element mode
l for dart:async", new CaughtException(exception, stackTrace)); |
| 8145 return VoidTypeImpl.instance; |
| 8146 } |
| 8147 } |
| 8148 |
| 8149 /** |
| 8150 * Answer `true` if the receiver directly or indirectly imports the dart:html
libraries. |
| 8151 * |
| 8152 * @return `true` if the receiver directly or indirectly imports the dart:html
libraries |
| 8153 */ |
| 8154 bool get isOrImportsBrowserLibrary { |
| 8155 List<LibraryElement> visited = new List<LibraryElement>(); |
| 8156 Source htmlLibSource = context.sourceFactory.forUri(DartSdk.DART_HTML); |
| 8157 visited.add(this); |
| 8158 for (int index = 0; index < visited.length; index++) { |
| 8159 LibraryElement library = visited[index]; |
| 8160 Source source = library.definingCompilationUnit.source; |
| 8161 if (source == htmlLibSource) { |
| 8162 return true; |
| 8163 } |
| 8164 for (LibraryElement importedLibrary in library.importedLibraries) { |
| 8165 if (!visited.contains(importedLibrary)) { |
| 8166 visited.add(importedLibrary); |
| 8167 } |
| 8168 } |
| 8169 for (LibraryElement exportedLibrary in library.exportedLibraries) { |
| 8170 if (!visited.contains(exportedLibrary)) { |
| 8171 visited.add(exportedLibrary); |
| 8172 } |
| 8173 } |
| 8174 } |
| 8175 return false; |
| 8176 } |
| 8177 } |
| 8178 |
| 8179 /** |
| 8180 * The interface `LocalElement` defines the behavior of elements that can be (bu
t are not |
| 8181 * required to be) defined within a method or function (an [ExecutableElement]). |
| 8182 */ |
| 8183 abstract class LocalElement implements Element { |
| 8184 /** |
| 8185 * Return a source range that covers the approximate portion of the source in
which the name of |
| 8186 * this element is visible, or `null` if there is no single range of character
s within which |
| 8187 * the element name is visible. |
| 8188 * * For a local variable, this includes everything from the end of the variab
le's initializer |
| 8189 * to the end of the block that encloses the variable declaration. |
| 8190 * * For a parameter, this includes the body of the method or function that de
clares the |
| 8191 * parameter. |
| 8192 * * For a local function, this includes everything from the beginning of the
function's body to |
| 8193 * the end of the block that encloses the function declaration. |
| 8194 * * For top-level functions, `null` will be returned because they are potenti
ally visible |
| 8195 * in multiple sources. |
| 8196 * |
| 8197 * @return the range of characters in which the name of this element is visibl
e |
| 8198 */ |
| 8199 SourceRange get visibleRange; |
| 8200 } |
| 8201 |
| 8202 /** |
| 8203 * The interface `LocalVariableElement` defines the behavior common to elements
that represent |
| 8204 * a local variable. |
| 8205 */ |
| 8206 abstract class LocalVariableElement implements LocalElement, VariableElement { |
| 8207 /** |
| 8208 * Return an array containing all of the toolkit specific objects attached to
this variable. |
| 8209 * |
| 8210 * @return the toolkit objects attached to this variable |
| 8211 */ |
| 8212 List<ToolkitObjectElement> get toolkitObjects; |
| 8213 } |
| 8214 |
| 8215 /** |
| 8216 * Instances of the class `LocalVariableElementImpl` implement a `LocalVariableE
lement`. |
| 8217 */ |
| 8218 class LocalVariableElementImpl extends VariableElementImpl implements LocalVaria
bleElement { |
| 8219 /** |
| 8220 * The offset to the beginning of the visible range for this element. |
| 8221 */ |
| 8222 int _visibleRangeOffset = 0; |
| 8223 |
| 8224 /** |
| 8225 * The length of the visible range for this element, or `-1` if this element d
oes not have a |
| 8226 * visible range. |
| 8227 */ |
| 8228 int _visibleRangeLength = -1; |
| 8229 |
| 8230 /** |
| 8231 * An empty array of field elements. |
| 8232 */ |
| 8233 static List<LocalVariableElement> EMPTY_ARRAY = new List<LocalVariableElement>
(0); |
| 8234 |
| 8235 /** |
| 8236 * Initialize a newly created local variable element to have the given name. |
| 8237 * |
| 8238 * @param name the name of this element |
| 8239 */ |
| 8240 LocalVariableElementImpl.forNode(Identifier name) : super.forNode(name); |
| 8241 |
| 8242 /** |
| 8243 * Initialize a newly created method element to have the given name. |
| 8244 * |
| 8245 * @param name the name of this element |
| 8246 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 8247 * declaration of this element |
| 8248 */ |
| 8249 LocalVariableElementImpl(String name, int nameOffset) : super(name, nameOffset
); |
| 8250 |
| 8251 @override |
| 8252 accept(ElementVisitor visitor) => visitor.visitLocalVariableElement(this); |
| 8253 |
| 8254 @override |
| 8255 ElementKind get kind => ElementKind.LOCAL_VARIABLE; |
| 8256 |
| 8257 @override |
| 8258 List<ToolkitObjectElement> get toolkitObjects { |
| 8259 CompilationUnitElementImpl unit = getAncestor((element) => element is Compil
ationUnitElementImpl); |
| 8260 if (unit == null) { |
| 8261 return ToolkitObjectElement.EMPTY_ARRAY; |
| 8262 } |
| 8263 return unit._getToolkitObjects(this); |
| 8264 } |
| 8265 |
| 8266 @override |
| 8267 SourceRange get visibleRange { |
| 8268 if (_visibleRangeLength < 0) { |
| 8269 return null; |
| 8270 } |
| 8271 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); |
| 8272 } |
| 8273 |
| 8274 @override |
| 8275 bool get isPotentiallyMutatedInClosure => hasModifier(Modifier.POTENTIALLY_MUT
ATED_IN_CONTEXT); |
| 8276 |
| 8277 @override |
| 8278 bool get isPotentiallyMutatedInScope => hasModifier(Modifier.POTENTIALLY_MUTAT
ED_IN_SCOPE); |
| 8279 |
| 8280 /** |
| 8281 * Specifies that this variable is potentially mutated somewhere in closure. |
| 8282 */ |
| 8283 void markPotentiallyMutatedInClosure() { |
| 8284 setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true); |
| 8285 } |
| 8286 |
| 8287 /** |
| 8288 * Specifies that this variable is potentially mutated somewhere in its scope. |
| 8289 */ |
| 8290 void markPotentiallyMutatedInScope() { |
| 8291 setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true); |
| 8292 } |
| 8293 |
| 8294 /** |
| 8295 * Set the toolkit specific information objects attached to this variable. |
| 8296 * |
| 8297 * @param toolkitObjects the toolkit objects attached to this variable |
| 8298 */ |
| 8299 void set toolkitObjects(List<ToolkitObjectElement> toolkitObjects) { |
| 8300 CompilationUnitElementImpl unit = getAncestor((element) => element is Compil
ationUnitElementImpl); |
| 8301 if (unit == null) { |
| 8302 return; |
| 8303 } |
| 8304 unit._setToolkitObjects(this, toolkitObjects); |
| 8305 } |
| 8306 |
| 8307 /** |
| 8308 * Set the visible range for this element to the range starting at the given o
ffset with the given |
| 8309 * length. |
| 8310 * |
| 8311 * @param offset the offset to the beginning of the visible range for this ele
ment |
| 8312 * @param length the length of the visible range for this element, or `-1` if
this element |
| 8313 * does not have a visible range |
| 8314 */ |
| 8315 void setVisibleRange(int offset, int length) { |
| 8316 _visibleRangeOffset = offset; |
| 8317 _visibleRangeLength = length; |
| 8318 } |
| 8319 |
| 8320 @override |
| 8321 void appendTo(JavaStringBuilder builder) { |
| 8322 builder.append(type); |
| 8323 builder.append(" "); |
| 8324 builder.append(displayName); |
| 8325 } |
| 8326 |
| 8327 @override |
| 8328 String get identifier => "${super.identifier}@${nameOffset}"; |
| 8329 } |
| 8330 |
| 8331 /** |
| 8332 * The abstract class `Member` defines the behavior common to elements that repr
esent members |
| 8333 * of parameterized types. |
| 8334 */ |
| 8335 abstract class Member implements Element { |
| 8336 /** |
| 8337 * The element on which the parameterized element was created. |
| 8338 */ |
| 8339 final Element _baseElement; |
| 8340 |
| 8341 /** |
| 8342 * The type in which the element is defined. |
| 8343 */ |
| 8344 final ParameterizedType _definingType; |
| 8345 |
| 8346 /** |
| 8347 * Initialize a newly created element to represent the member of the given par
ameterized type. |
| 8348 * |
| 8349 * @param baseElement the element on which the parameterized element was creat
ed |
| 8350 * @param definingType the type in which the element is defined |
| 8351 */ |
| 8352 Member(this._baseElement, this._definingType); |
| 8353 |
| 8354 @override |
| 8355 String computeDocumentationComment() => _baseElement.computeDocumentationComme
nt(); |
| 8356 |
| 8357 @override |
| 8358 Element getAncestor(Predicate<Element> predicate) => baseElement.getAncestor(p
redicate); |
| 8359 |
| 8360 /** |
| 8361 * Return the element on which the parameterized element was created. |
| 8362 * |
| 8363 * @return the element on which the parameterized element was created |
| 8364 */ |
| 8365 Element get baseElement => _baseElement; |
| 8366 |
| 8367 @override |
| 8368 AnalysisContext get context => _baseElement.context; |
| 8369 |
| 8370 @override |
| 8371 String get displayName => _baseElement.displayName; |
| 8372 |
| 8373 @override |
| 8374 String getExtendedDisplayName(String shortName) => _baseElement.getExtendedDis
playName(shortName); |
| 8375 |
| 8376 @override |
| 8377 ElementKind get kind => _baseElement.kind; |
| 8378 |
| 8379 @override |
| 8380 LibraryElement get library => _baseElement.library; |
| 8381 |
| 8382 @override |
| 8383 ElementLocation get location => _baseElement.location; |
| 8384 |
| 8385 @override |
| 8386 List<ElementAnnotation> get metadata => _baseElement.metadata; |
| 8387 |
| 8388 @override |
| 8389 String get name => _baseElement.name; |
| 8390 |
| 8391 @override |
| 8392 int get nameOffset => _baseElement.nameOffset; |
| 8393 |
| 8394 @override |
| 8395 AstNode get node => _baseElement.node; |
| 8396 |
| 8397 @override |
| 8398 Source get source => _baseElement.source; |
| 8399 |
| 8400 @override |
| 8401 CompilationUnit get unit => _baseElement.unit; |
| 8402 |
| 8403 @override |
| 8404 bool isAccessibleIn(LibraryElement library) => _baseElement.isAccessibleIn(lib
rary); |
| 8405 |
| 8406 @override |
| 8407 bool get isDeprecated => _baseElement.isDeprecated; |
| 8408 |
| 8409 @override |
| 8410 bool get isOverride => _baseElement.isOverride; |
| 8411 |
| 8412 @override |
| 8413 bool get isPrivate => _baseElement.isPrivate; |
| 8414 |
| 8415 @override |
| 8416 bool get isPublic => _baseElement.isPublic; |
| 8417 |
| 8418 @override |
| 8419 bool get isSynthetic => _baseElement.isSynthetic; |
| 8420 |
| 8421 @override |
| 8422 void visitChildren(ElementVisitor visitor) { |
| 8423 } |
| 8424 |
| 8425 /** |
| 8426 * Return the type in which the element is defined. |
| 8427 * |
| 8428 * @return the type in which the element is defined |
| 8429 */ |
| 8430 ParameterizedType get definingType => _definingType; |
| 8431 |
| 8432 /** |
| 8433 * If the given child is not `null`, use the given visitor to visit it. |
| 8434 * |
| 8435 * @param child the child to be visited |
| 8436 * @param visitor the visitor to be used to visit the child |
| 8437 */ |
| 8438 void safelyVisitChild(Element child, ElementVisitor visitor) { |
| 8439 if (child != null) { |
| 8440 child.accept(visitor); |
| 8441 } |
| 8442 } |
| 8443 |
| 8444 /** |
| 8445 * Use the given visitor to visit all of the children in the given array. |
| 8446 * |
| 8447 * @param children the children to be visited |
| 8448 * @param visitor the visitor being used to visit the children |
| 8449 */ |
| 8450 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) { |
| 8451 if (children != null) { |
| 8452 for (Element child in children) { |
| 8453 child.accept(visitor); |
| 8454 } |
| 8455 } |
| 8456 } |
| 8457 |
| 8458 /** |
| 8459 * Return the type that results from replacing the type parameters in the give
n type with the type |
| 8460 * arguments. |
| 8461 * |
| 8462 * @param type the type to be transformed |
| 8463 * @return the result of transforming the type |
| 8464 */ |
| 8465 DartType substituteFor(DartType type) { |
| 8466 if (type == null) { |
| 8467 return null; |
| 8468 } |
| 8469 List<DartType> argumentTypes = _definingType.typeArguments; |
| 8470 List<DartType> parameterTypes = TypeParameterTypeImpl.getTypes(_definingType
.typeParameters); |
| 8471 return type.substitute2(argumentTypes, parameterTypes); |
| 8472 } |
| 8473 |
| 8474 /** |
| 8475 * Return the array of types that results from replacing the type parameters i
n the given types |
| 8476 * with the type arguments. |
| 8477 * |
| 8478 * @param types the types to be transformed |
| 8479 * @return the result of transforming the types |
| 8480 */ |
| 8481 List<InterfaceType> substituteFor2(List<InterfaceType> types) { |
| 8482 int count = types.length; |
| 8483 List<InterfaceType> substitutedTypes = new List<InterfaceType>(count); |
| 8484 for (int i = 0; i < count; i++) { |
| 8485 substitutedTypes[i] = substituteFor(types[i]); |
| 8486 } |
| 8487 return substitutedTypes; |
| 8488 } |
| 8489 } |
| 8490 |
| 8491 /** |
| 8492 * The interface `MethodElement` defines the behavior of elements that represent
a method |
| 8493 * defined within a type. |
| 8494 */ |
| 8495 abstract class MethodElement implements ClassMemberElement, ExecutableElement { |
| 8496 /** |
| 8497 * Return the resolved [MethodDeclaration] node that declares this [MethodElem
ent]. |
| 8498 * |
| 8499 * This method is expensive, because resolved AST might be evicted from cache,
so parsing and |
| 8500 * resolving will be performed. |
| 8501 * |
| 8502 * @return the resolved [MethodDeclaration], not `null`. |
| 8503 */ |
| 8504 @override |
| 8505 MethodDeclaration get node; |
| 8506 |
| 8507 /** |
| 8508 * Return `true` if this method is abstract. Methods are abstract if they are
not external |
| 8509 * and have no body. |
| 8510 * |
| 8511 * @return `true` if this method is abstract |
| 8512 */ |
| 8513 bool get isAbstract; |
| 8514 } |
| 8515 |
| 8516 /** |
| 8517 * Instances of the class `MethodElementImpl` implement a `MethodElement`. |
| 8518 */ |
| 8519 class MethodElementImpl extends ExecutableElementImpl implements MethodElement { |
| 8520 /** |
| 8521 * An empty array of method elements. |
| 8522 */ |
| 8523 static List<MethodElement> EMPTY_ARRAY = new List<MethodElement>(0); |
| 8524 |
| 8525 /** |
| 8526 * Initialize a newly created method element to have the given name. |
| 8527 * |
| 8528 * @param name the name of this element |
| 8529 */ |
| 8530 MethodElementImpl.forNode(Identifier name) : super.forNode(name); |
| 8531 |
| 8532 /** |
| 8533 * Initialize a newly created method element to have the given name. |
| 8534 * |
| 8535 * @param name the name of this element |
| 8536 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 8537 * declaration of this element |
| 8538 */ |
| 8539 MethodElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 8540 |
| 8541 @override |
| 8542 accept(ElementVisitor visitor) => visitor.visitMethodElement(this); |
| 8543 |
| 8544 @override |
| 8545 String get displayName { |
| 8546 String displayName = super.displayName; |
| 8547 if ("unary-" == displayName) { |
| 8548 return "-"; |
| 8549 } |
| 8550 return displayName; |
| 8551 } |
| 8552 |
| 8553 @override |
| 8554 ClassElement get enclosingElement => super.enclosingElement as ClassElement; |
| 8555 |
| 8556 @override |
| 8557 ElementKind get kind => ElementKind.METHOD; |
| 8558 |
| 8559 @override |
| 8560 String get name { |
| 8561 String name = super.name; |
| 8562 if (isOperator && name == "-") { |
| 8563 if (parameters.length == 0) { |
| 8564 return "unary-"; |
| 8565 } |
| 8566 } |
| 8567 return super.name; |
| 8568 } |
| 8569 |
| 8570 @override |
| 8571 MethodDeclaration get node => getNodeMatching((node) => node is MethodDeclarat
ion); |
| 8572 |
| 8573 @override |
| 8574 bool get isAbstract => hasModifier(Modifier.ABSTRACT); |
| 8575 |
| 8576 @override |
| 8577 bool get isOperator { |
| 8578 String name = displayName; |
| 8579 if (name.isEmpty) { |
| 8580 return false; |
| 8581 } |
| 8582 int first = name.codeUnitAt(0); |
| 8583 return !((0x61 <= first && first <= 0x7A) || (0x41 <= first && first <= 0x5A
) || first == 0x5F || first == 0x24); |
| 8584 } |
| 8585 |
| 8586 @override |
| 8587 bool get isStatic => hasModifier(Modifier.STATIC); |
| 8588 |
| 8589 /** |
| 8590 * Set whether this method is abstract to correspond to the given value. |
| 8591 * |
| 8592 * @param isAbstract `true` if the method is abstract |
| 8593 */ |
| 8594 void set abstract(bool isAbstract) { |
| 8595 setModifier(Modifier.ABSTRACT, isAbstract); |
| 8596 } |
| 8597 |
| 8598 /** |
| 8599 * Set whether this method is static to correspond to the given value. |
| 8600 * |
| 8601 * @param isStatic `true` if the method is static |
| 8602 */ |
| 8603 void set static(bool isStatic) { |
| 8604 setModifier(Modifier.STATIC, isStatic); |
| 8605 } |
| 8606 |
| 8607 @override |
| 8608 void appendTo(JavaStringBuilder builder) { |
| 8609 builder.append(enclosingElement.displayName); |
| 8610 builder.append("."); |
| 8611 builder.append(displayName); |
| 8612 super.appendTo(builder); |
| 8613 } |
| 8614 } |
| 8615 |
| 8616 /** |
| 8617 * Instances of the class `MethodMember` represent a method element defined in a
parameterized |
| 8618 * type where the values of the type parameters are known. |
| 8619 */ |
| 8620 class MethodMember extends ExecutableMember implements MethodElement { |
| 8621 /** |
| 8622 * If the given method's type is different when any type parameters from the d
efining type's |
| 8623 * declaration are replaced with the actual type arguments from the defining t
ype, create a method |
| 8624 * member representing the given method. Return the member that was created, o
r the base method if |
| 8625 * no member was created. |
| 8626 * |
| 8627 * @param baseMethod the base method for which a member might be created |
| 8628 * @param definingType the type defining the parameters and arguments to be us
ed in the |
| 8629 * substitution |
| 8630 * @return the method element that will return the correctly substituted types |
| 8631 */ |
| 8632 static MethodElement from(MethodElement baseMethod, InterfaceType definingType
) { |
| 8633 if (baseMethod == null || definingType.typeArguments.length == 0) { |
| 8634 return baseMethod; |
| 8635 } |
| 8636 FunctionType baseType = baseMethod.type; |
| 8637 List<DartType> argumentTypes = definingType.typeArguments; |
| 8638 List<DartType> parameterTypes = definingType.element.type.typeArguments; |
| 8639 FunctionType substitutedType = baseType.substitute2(argumentTypes, parameter
Types); |
| 8640 if (baseType == substitutedType) { |
| 8641 return baseMethod; |
| 8642 } |
| 8643 // TODO(brianwilkerson) Consider caching the substituted type in the instanc
e. It would use more |
| 8644 // memory but speed up some operations. We need to see how often the type is
being re-computed. |
| 8645 return new MethodMember(baseMethod, definingType); |
| 8646 } |
| 8647 |
| 8648 /** |
| 8649 * Initialize a newly created element to represent a method of the given param
eterized type. |
| 8650 * |
| 8651 * @param baseElement the element on which the parameterized element was creat
ed |
| 8652 * @param definingType the type in which the element is defined |
| 8653 */ |
| 8654 MethodMember(MethodElement baseElement, InterfaceType definingType) : super(ba
seElement, definingType); |
| 8655 |
| 8656 @override |
| 8657 accept(ElementVisitor visitor) => visitor.visitMethodElement(this); |
| 8658 |
| 8659 @override |
| 8660 MethodElement get baseElement => super.baseElement as MethodElement; |
| 8661 |
| 8662 @override |
| 8663 ClassElement get enclosingElement => baseElement.enclosingElement; |
| 8664 |
| 8665 @override |
| 8666 MethodDeclaration get node => baseElement.node; |
| 8667 |
| 8668 @override |
| 8669 bool get isAbstract => baseElement.isAbstract; |
| 8670 |
| 8671 @override |
| 8672 String toString() { |
| 8673 MethodElement baseElement = this.baseElement; |
| 8674 List<ParameterElement> parameters = this.parameters; |
| 8675 FunctionType type = this.type; |
| 8676 JavaStringBuilder builder = new JavaStringBuilder(); |
| 8677 builder.append(baseElement.enclosingElement.displayName); |
| 8678 builder.append("."); |
| 8679 builder.append(baseElement.displayName); |
| 8680 builder.append("("); |
| 8681 int parameterCount = parameters.length; |
| 8682 for (int i = 0; i < parameterCount; i++) { |
| 8683 if (i > 0) { |
| 8684 builder.append(", "); |
| 8685 } |
| 8686 builder.append(parameters[i]).toString(); |
| 8687 } |
| 8688 builder.append(")"); |
| 8689 if (type != null) { |
| 8690 builder.append(Element.RIGHT_ARROW); |
| 8691 builder.append(type.returnType); |
| 8692 } |
| 8693 return builder.toString(); |
| 8694 } |
| 8695 } |
| 8696 |
| 8697 /** |
| 8698 * The enumeration `Modifier` defines constants for all of the modifiers defined
by the Dart |
| 8699 * language and for a few additional flags that are useful. |
| 8700 */ |
| 8701 class Modifier extends Enum<Modifier> { |
| 8702 /** |
| 8703 * Indicates that the modifier 'abstract' was applied to the element. |
| 8704 */ |
| 8705 static const Modifier ABSTRACT = const Modifier('ABSTRACT', 0); |
| 8706 |
| 8707 /** |
| 8708 * Indicates that an executable element has a body marked as being asynchronou
s. |
| 8709 */ |
| 8710 static const Modifier ASYNCHRONOUS = const Modifier('ASYNCHRONOUS', 1); |
| 8711 |
| 8712 /** |
| 8713 * Indicates that the modifier 'const' was applied to the element. |
| 8714 */ |
| 8715 static const Modifier CONST = const Modifier('CONST', 2); |
| 8716 |
| 8717 /** |
| 8718 * Indicates that the import element represents a deferred library. |
| 8719 */ |
| 8720 static const Modifier DEFERRED = const Modifier('DEFERRED', 3); |
| 8721 |
| 8722 /** |
| 8723 * Indicates that a class element was defined by an enum declaration. |
| 8724 */ |
| 8725 static const Modifier ENUM = const Modifier('ENUM', 4); |
| 8726 |
| 8727 /** |
| 8728 * Indicates that the modifier 'factory' was applied to the element. |
| 8729 */ |
| 8730 static const Modifier FACTORY = const Modifier('FACTORY', 5); |
| 8731 |
| 8732 /** |
| 8733 * Indicates that the modifier 'final' was applied to the element. |
| 8734 */ |
| 8735 static const Modifier FINAL = const Modifier('FINAL', 6); |
| 8736 |
| 8737 /** |
| 8738 * Indicates that an executable element has a body marked as being a generator
. |
| 8739 */ |
| 8740 static const Modifier GENERATOR = const Modifier('GENERATOR', 7); |
| 8741 |
| 8742 /** |
| 8743 * Indicates that the pseudo-modifier 'get' was applied to the element. |
| 8744 */ |
| 8745 static const Modifier GETTER = const Modifier('GETTER', 8); |
| 8746 |
| 8747 /** |
| 8748 * A flag used for libraries indicating that the defining compilation unit con
tains at least one |
| 8749 * import directive whose URI uses the "dart-ext" scheme. |
| 8750 */ |
| 8751 static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 9); |
| 8752 |
| 8753 /** |
| 8754 * Indicates that a class can validly be used as a mixin. |
| 8755 */ |
| 8756 static const Modifier MIXIN = const Modifier('MIXIN', 10); |
| 8757 |
| 8758 /** |
| 8759 * Indicates that the value of a parameter or local variable might be mutated
within the context. |
| 8760 */ |
| 8761 static const Modifier POTENTIALLY_MUTATED_IN_CONTEXT = const Modifier('POTENTI
ALLY_MUTATED_IN_CONTEXT', 11); |
| 8762 |
| 8763 /** |
| 8764 * Indicates that the value of a parameter or local variable might be mutated
within the scope. |
| 8765 */ |
| 8766 static const Modifier POTENTIALLY_MUTATED_IN_SCOPE = const Modifier('POTENTIAL
LY_MUTATED_IN_SCOPE', 12); |
| 8767 |
| 8768 /** |
| 8769 * Indicates that a class contains an explicit reference to 'super'. |
| 8770 */ |
| 8771 static const Modifier REFERENCES_SUPER = const Modifier('REFERENCES_SUPER', 13
); |
| 8772 |
| 8773 /** |
| 8774 * Indicates that the pseudo-modifier 'set' was applied to the element. |
| 8775 */ |
| 8776 static const Modifier SETTER = const Modifier('SETTER', 14); |
| 8777 |
| 8778 /** |
| 8779 * Indicates that the modifier 'static' was applied to the element. |
| 8780 */ |
| 8781 static const Modifier STATIC = const Modifier('STATIC', 15); |
| 8782 |
| 8783 /** |
| 8784 * Indicates that the element does not appear in the source code but was impli
citly created. For |
| 8785 * example, if a class does not define any constructors, an implicit zero-argu
ment constructor |
| 8786 * will be created and it will be marked as being synthetic. |
| 8787 */ |
| 8788 static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 16); |
| 8789 |
| 8790 /** |
| 8791 * Indicates that a class was defined using an alias. TODO(brianwilkerson) Thi
s should be renamed |
| 8792 * to 'ALIAS'. |
| 8793 */ |
| 8794 static const Modifier TYPEDEF = const Modifier('TYPEDEF', 17); |
| 8795 |
| 8796 static const List<Modifier> values = const [ |
| 8797 ABSTRACT, |
| 8798 ASYNCHRONOUS, |
| 8799 CONST, |
| 8800 DEFERRED, |
| 8801 ENUM, |
| 8802 FACTORY, |
| 8803 FINAL, |
| 8804 GENERATOR, |
| 8805 GETTER, |
| 8806 HAS_EXT_URI, |
| 8807 MIXIN, |
| 8808 POTENTIALLY_MUTATED_IN_CONTEXT, |
| 8809 POTENTIALLY_MUTATED_IN_SCOPE, |
| 8810 REFERENCES_SUPER, |
| 8811 SETTER, |
| 8812 STATIC, |
| 8813 SYNTHETIC, |
| 8814 TYPEDEF]; |
| 8815 |
| 8816 const Modifier(String name, int ordinal) : super(name, ordinal); |
| 8817 } |
| 8818 |
| 8819 /** |
| 8820 * The interface `MultiplyDefinedElement` defines the behavior of pseudo-element
s that |
| 8821 * represent multiple elements defined within a single scope that have the same
name. This situation |
| 8822 * is not allowed by the language, so objects implementing this interface always
represent an error. |
| 8823 * As a result, most of the normal operations on elements do not make sense and
will return useless |
| 8824 * results. |
| 8825 */ |
| 8826 abstract class MultiplyDefinedElement implements Element { |
| 8827 /** |
| 8828 * Return an array containing all of the elements that were defined within the
scope to have the |
| 8829 * same name. |
| 8830 * |
| 8831 * @return the elements that were defined with the same name |
| 8832 */ |
| 8833 List<Element> get conflictingElements; |
| 8834 |
| 8835 /** |
| 8836 * Return the type of this element as the dynamic type. |
| 8837 * |
| 8838 * @return the type of this element as the dynamic type |
| 8839 */ |
| 8840 DartType get type; |
| 8841 } |
| 8842 |
| 8843 /** |
| 8844 * Instances of the class `MultiplyDefinedElementImpl` represent a collection of
elements that |
| 8845 * have the same name within the same scope. |
| 8846 */ |
| 8847 class MultiplyDefinedElementImpl implements MultiplyDefinedElement { |
| 8848 /** |
| 8849 * Return an element that represents the given conflicting elements. |
| 8850 * |
| 8851 * @param context the analysis context in which the multiply defined elements
are defined |
| 8852 * @param firstElement the first element that conflicts |
| 8853 * @param secondElement the second element that conflicts |
| 8854 */ |
| 8855 static Element fromElements(AnalysisContext context, Element firstElement, Ele
ment secondElement) { |
| 8856 List<Element> conflictingElements = _computeConflictingElements(firstElement
, secondElement); |
| 8857 int length = conflictingElements.length; |
| 8858 if (length == 0) { |
| 8859 return null; |
| 8860 } else if (length == 1) { |
| 8861 return conflictingElements[0]; |
| 8862 } |
| 8863 return new MultiplyDefinedElementImpl(context, conflictingElements); |
| 8864 } |
| 8865 |
| 8866 /** |
| 8867 * Add the given element to the list of elements. If the element is a multiply
-defined element, |
| 8868 * add all of the conflicting elements that it represents. |
| 8869 * |
| 8870 * @param elements the list to which the element(s) are to be added |
| 8871 * @param element the element(s) to be added |
| 8872 */ |
| 8873 static void _add(HashSet<Element> elements, Element element) { |
| 8874 if (element is MultiplyDefinedElementImpl) { |
| 8875 for (Element conflictingElement in element.conflictingElements) { |
| 8876 elements.add(conflictingElement); |
| 8877 } |
| 8878 } else { |
| 8879 elements.add(element); |
| 8880 } |
| 8881 } |
| 8882 |
| 8883 /** |
| 8884 * Use the given elements to construct an array of conflicting elements. If ei
ther of the given |
| 8885 * elements are multiply-defined elements then the conflicting elements they r
epresent will be |
| 8886 * included in the array. Otherwise, the element itself will be included. |
| 8887 * |
| 8888 * @param firstElement the first element to be included |
| 8889 * @param secondElement the second element to be included |
| 8890 * @return an array containing all of the conflicting elements |
| 8891 */ |
| 8892 static List<Element> _computeConflictingElements(Element firstElement, Element
secondElement) { |
| 8893 HashSet<Element> elements = new HashSet<Element>(); |
| 8894 _add(elements, firstElement); |
| 8895 _add(elements, secondElement); |
| 8896 return new List.from(elements); |
| 8897 } |
| 8898 |
| 8899 /** |
| 8900 * The analysis context in which the multiply defined elements are defined. |
| 8901 */ |
| 8902 final AnalysisContext context; |
| 8903 |
| 8904 /** |
| 8905 * The name of the conflicting elements. |
| 8906 */ |
| 8907 String _name; |
| 8908 |
| 8909 /** |
| 8910 * A list containing all of the elements that conflict. |
| 8911 */ |
| 8912 final List<Element> conflictingElements; |
| 8913 |
| 8914 /** |
| 8915 * Initialize a newly created element to represent a list of conflicting eleme
nts. |
| 8916 * |
| 8917 * @param context the analysis context in which the multiply defined elements
are defined |
| 8918 * @param conflictingElements the elements that conflict |
| 8919 */ |
| 8920 MultiplyDefinedElementImpl(this.context, this.conflictingElements) { |
| 8921 _name = conflictingElements[0].name; |
| 8922 } |
| 8923 |
| 8924 @override |
| 8925 accept(ElementVisitor visitor) => visitor.visitMultiplyDefinedElement(this); |
| 8926 |
| 8927 @override |
| 8928 String computeDocumentationComment() => null; |
| 8929 |
| 8930 @override |
| 8931 Element getAncestor(Predicate<Element> predicate) => null; |
| 8932 |
| 8933 @override |
| 8934 String get displayName => _name; |
| 8935 |
| 8936 @override |
| 8937 Element get enclosingElement => null; |
| 8938 |
| 8939 @override |
| 8940 String getExtendedDisplayName(String shortName) { |
| 8941 if (shortName != null) { |
| 8942 return shortName; |
| 8943 } |
| 8944 return displayName; |
| 8945 } |
| 8946 |
| 8947 @override |
| 8948 ElementKind get kind => ElementKind.ERROR; |
| 8949 |
| 8950 @override |
| 8951 LibraryElement get library => null; |
| 8952 |
| 8953 @override |
| 8954 ElementLocation get location => null; |
| 8955 |
| 8956 @override |
| 8957 List<ElementAnnotation> get metadata => ElementAnnotationImpl.EMPTY_ARRAY; |
| 8958 |
| 8959 @override |
| 8960 String get name => _name; |
| 8961 |
| 8962 @override |
| 8963 int get nameOffset => -1; |
| 8964 |
| 8965 @override |
| 8966 AstNode get node => null; |
| 8967 |
| 8968 @override |
| 8969 Source get source => null; |
| 8970 |
| 8971 @override |
| 8972 DartType get type => DynamicTypeImpl.instance; |
| 8973 |
| 8974 @override |
| 8975 CompilationUnit get unit => null; |
| 8976 |
| 8977 @override |
| 8978 bool isAccessibleIn(LibraryElement library) { |
| 8979 for (Element element in conflictingElements) { |
| 8980 if (element.isAccessibleIn(library)) { |
| 8981 return true; |
| 8982 } |
| 8983 } |
| 8984 return false; |
| 8985 } |
| 8986 |
| 8987 @override |
| 8988 bool get isDeprecated => false; |
| 8989 |
| 8990 @override |
| 8991 bool get isOverride => false; |
| 8992 |
| 8993 @override |
| 8994 bool get isPrivate { |
| 8995 String name = displayName; |
| 8996 if (name == null) { |
| 8997 return false; |
| 8998 } |
| 8999 return Identifier.isPrivateName(name); |
| 9000 } |
| 9001 |
| 9002 @override |
| 9003 bool get isPublic => !isPrivate; |
| 9004 |
| 9005 @override |
| 9006 bool get isSynthetic => true; |
| 9007 |
| 9008 @override |
| 9009 String toString() { |
| 9010 JavaStringBuilder builder = new JavaStringBuilder(); |
| 9011 builder.append("["); |
| 9012 int count = conflictingElements.length; |
| 9013 for (int i = 0; i < count; i++) { |
| 9014 if (i > 0) { |
| 9015 builder.append(", "); |
| 9016 } |
| 9017 (conflictingElements[i] as ElementImpl).appendTo(builder); |
| 9018 } |
| 9019 builder.append("]"); |
| 9020 return builder.toString(); |
| 9021 } |
| 9022 |
| 9023 @override |
| 9024 void visitChildren(ElementVisitor visitor) { |
| 9025 } |
| 9026 } |
| 9027 |
| 9028 /** |
| 9029 * The interface [MultiplyInheritedExecutableElement] defines all of the behavio
r of an |
| 9030 * [ExecutableElement], with the additional information of an array of |
| 9031 * [ExecutableElement]s from which this element was composed. |
| 9032 */ |
| 9033 abstract class MultiplyInheritedExecutableElement implements ExecutableElement { |
| 9034 /** |
| 9035 * Return an array containing all of the executable elements defined within th
is executable |
| 9036 * element. |
| 9037 * |
| 9038 * @return the elements defined within this executable element |
| 9039 */ |
| 9040 List<ExecutableElement> get inheritedElements; |
| 9041 } |
| 9042 |
| 9043 /** |
| 9044 * The interface [MultiplyInheritedMethodElementImpl] defines all of the behavio
r of an |
| 9045 * [MethodElementImpl], with the additional information of an array of |
| 9046 * [ExecutableElement]s from which this element was composed. |
| 9047 */ |
| 9048 class MultiplyInheritedMethodElementImpl extends MethodElementImpl implements Mu
ltiplyInheritedExecutableElement { |
| 9049 /** |
| 9050 * An array the array of executable elements that were used to compose this el
ement. |
| 9051 */ |
| 9052 List<ExecutableElement> _elements = MethodElementImpl.EMPTY_ARRAY; |
| 9053 |
| 9054 MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) { |
| 9055 synthetic = true; |
| 9056 } |
| 9057 |
| 9058 @override |
| 9059 List<ExecutableElement> get inheritedElements => _elements; |
| 9060 |
| 9061 void set inheritedElements(List<ExecutableElement> elements) { |
| 9062 this._elements = elements; |
| 9063 } |
| 9064 } |
| 9065 |
| 9066 /** |
| 9067 * The interface [MultiplyInheritedPropertyAccessorElementImpl] defines all of t
he behavior of |
| 9068 * an [PropertyAccessorElementImpl], with the additional information of an array
of |
| 9069 * [ExecutableElement]s from which this element was composed. |
| 9070 */ |
| 9071 class MultiplyInheritedPropertyAccessorElementImpl extends PropertyAccessorEleme
ntImpl implements MultiplyInheritedExecutableElement { |
| 9072 /** |
| 9073 * An array the array of executable elements that were used to compose this el
ement. |
| 9074 */ |
| 9075 List<ExecutableElement> _elements = PropertyAccessorElementImpl.EMPTY_ARRAY; |
| 9076 |
| 9077 MultiplyInheritedPropertyAccessorElementImpl(Identifier name) : super.forNode(
name) { |
| 9078 synthetic = true; |
| 9079 } |
| 9080 |
| 9081 @override |
| 9082 List<ExecutableElement> get inheritedElements => _elements; |
| 9083 |
| 9084 void set inheritedElements(List<ExecutableElement> elements) { |
| 9085 this._elements = elements; |
| 9086 } |
| 9087 } |
| 9088 |
| 9089 /** |
| 9090 * The interface `NamespaceCombinator` defines the behavior common to objects th
at control how |
| 9091 * namespaces are combined. |
| 9092 */ |
| 9093 abstract class NamespaceCombinator { |
| 9094 /** |
| 9095 * An empty array of namespace combinators. |
| 9096 */ |
| 9097 static final List<NamespaceCombinator> EMPTY_ARRAY = new List<NamespaceCombina
tor>(0); |
| 9098 } |
| 9099 |
| 9100 /** |
| 9101 * The interface `ParameterElement` defines the behavior of elements representin
g a parameter |
| 9102 * defined within an executable element. |
| 9103 */ |
| 9104 abstract class ParameterElement implements LocalElement, VariableElement { |
| 9105 /** |
| 9106 * Return a source range that covers the portion of the source in which the de
fault value for this |
| 9107 * parameter is specified, or `null` if there is no default value. |
| 9108 * |
| 9109 * @return the range of characters in which the default value of this paramete
r is specified |
| 9110 */ |
| 9111 SourceRange get defaultValueRange; |
| 9112 |
| 9113 /** |
| 9114 * Return the kind of this parameter. |
| 9115 * |
| 9116 * @return the kind of this parameter |
| 9117 */ |
| 9118 ParameterKind get parameterKind; |
| 9119 |
| 9120 /** |
| 9121 * Return an array containing all of the parameters defined by this parameter.
A parameter will |
| 9122 * only define other parameters if it is a function typed parameter. |
| 9123 * |
| 9124 * @return the parameters defined by this parameter element |
| 9125 */ |
| 9126 List<ParameterElement> get parameters; |
| 9127 |
| 9128 /** |
| 9129 * Return `true` if this parameter is an initializing formal parameter. |
| 9130 * |
| 9131 * @return `true` if this parameter is an initializing formal parameter |
| 9132 */ |
| 9133 bool get isInitializingFormal; |
| 9134 } |
| 9135 |
| 9136 /** |
| 9137 * Instances of the class `ParameterElementImpl` implement a `ParameterElement`. |
| 9138 */ |
| 9139 class ParameterElementImpl extends VariableElementImpl implements ParameterEleme
nt { |
| 9140 /** |
| 9141 * An array containing all of the parameters defined by this parameter element
. There will only be |
| 9142 * parameters if this parameter is a function typed parameter. |
| 9143 */ |
| 9144 List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY; |
| 9145 |
| 9146 /** |
| 9147 * The kind of this parameter. |
| 9148 */ |
| 9149 ParameterKind parameterKind; |
| 9150 |
| 9151 /** |
| 9152 * The offset to the beginning of the default value range for this element. |
| 9153 */ |
| 9154 int _defaultValueRangeOffset = 0; |
| 9155 |
| 9156 /** |
| 9157 * The length of the default value range for this element, or `-1` if this ele
ment does not |
| 9158 * have a default value. |
| 9159 */ |
| 9160 int _defaultValueRangeLength = -1; |
| 9161 |
| 9162 /** |
| 9163 * The offset to the beginning of the visible range for this element. |
| 9164 */ |
| 9165 int _visibleRangeOffset = 0; |
| 9166 |
| 9167 /** |
| 9168 * The length of the visible range for this element, or `-1` if this element d
oes not have a |
| 9169 * visible range. |
| 9170 */ |
| 9171 int _visibleRangeLength = -1; |
| 9172 |
| 9173 /** |
| 9174 * An empty array of field elements. |
| 9175 */ |
| 9176 static List<ParameterElement> EMPTY_ARRAY = new List<ParameterElement>(0); |
| 9177 |
| 9178 /** |
| 9179 * Initialize a newly created parameter element to have the given name. |
| 9180 * |
| 9181 * @param name the name of this element |
| 9182 */ |
| 9183 ParameterElementImpl.forNode(Identifier name) : super.forNode(name); |
| 9184 |
| 9185 /** |
| 9186 * Initialize a newly created parameter element to have the given name. |
| 9187 * |
| 9188 * @param name the name of this element |
| 9189 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 9190 * declaration of this element |
| 9191 */ |
| 9192 ParameterElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 9193 |
| 9194 @override |
| 9195 accept(ElementVisitor visitor) => visitor.visitParameterElement(this); |
| 9196 |
| 9197 @override |
| 9198 ElementImpl getChild(String identifier) { |
| 9199 for (ParameterElement parameter in _parameters) { |
| 9200 if ((parameter as ParameterElementImpl).identifier == identifier) { |
| 9201 return parameter as ParameterElementImpl; |
| 9202 } |
| 9203 } |
| 9204 return null; |
| 9205 } |
| 9206 |
| 9207 @override |
| 9208 SourceRange get defaultValueRange { |
| 9209 if (_defaultValueRangeLength < 0) { |
| 9210 return null; |
| 9211 } |
| 9212 return new SourceRange(_defaultValueRangeOffset, _defaultValueRangeLength); |
| 9213 } |
| 9214 |
| 9215 @override |
| 9216 ElementKind get kind => ElementKind.PARAMETER; |
| 9217 |
| 9218 @override |
| 9219 List<ParameterElement> get parameters => _parameters; |
| 9220 |
| 9221 @override |
| 9222 SourceRange get visibleRange { |
| 9223 if (_visibleRangeLength < 0) { |
| 9224 return null; |
| 9225 } |
| 9226 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); |
| 9227 } |
| 9228 |
| 9229 @override |
| 9230 bool get isInitializingFormal => false; |
| 9231 |
| 9232 @override |
| 9233 bool get isPotentiallyMutatedInClosure => hasModifier(Modifier.POTENTIALLY_MUT
ATED_IN_CONTEXT); |
| 9234 |
| 9235 @override |
| 9236 bool get isPotentiallyMutatedInScope => hasModifier(Modifier.POTENTIALLY_MUTAT
ED_IN_SCOPE); |
| 9237 |
| 9238 /** |
| 9239 * Specifies that this variable is potentially mutated somewhere in closure. |
| 9240 */ |
| 9241 void markPotentiallyMutatedInClosure() { |
| 9242 setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true); |
| 9243 } |
| 9244 |
| 9245 /** |
| 9246 * Specifies that this variable is potentially mutated somewhere in its scope. |
| 9247 */ |
| 9248 void markPotentiallyMutatedInScope() { |
| 9249 setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true); |
| 9250 } |
| 9251 |
| 9252 /** |
| 9253 * Set the range of the default value for this parameter to the range starting
at the given offset |
| 9254 * with the given length. |
| 9255 * |
| 9256 * @param offset the offset to the beginning of the default value range for th
is element |
| 9257 * @param length the length of the default value range for this element, or `-
1` if this |
| 9258 * element does not have a default value |
| 9259 */ |
| 9260 void setDefaultValueRange(int offset, int length) { |
| 9261 _defaultValueRangeOffset = offset; |
| 9262 _defaultValueRangeLength = length; |
| 9263 } |
| 9264 |
| 9265 /** |
| 9266 * Set the parameters defined by this executable element to the given paramete
rs. |
| 9267 * |
| 9268 * @param parameters the parameters defined by this executable element |
| 9269 */ |
| 9270 void set parameters(List<ParameterElement> parameters) { |
| 9271 for (ParameterElement parameter in parameters) { |
| 9272 (parameter as ParameterElementImpl).enclosingElement = this; |
| 9273 } |
| 9274 this._parameters = parameters; |
| 9275 } |
| 9276 |
| 9277 /** |
| 9278 * Set the visible range for this element to the range starting at the given o
ffset with the given |
| 9279 * length. |
| 9280 * |
| 9281 * @param offset the offset to the beginning of the visible range for this ele
ment |
| 9282 * @param length the length of the visible range for this element, or `-1` if
this element |
| 9283 * does not have a visible range |
| 9284 */ |
| 9285 void setVisibleRange(int offset, int length) { |
| 9286 _visibleRangeOffset = offset; |
| 9287 _visibleRangeLength = length; |
| 9288 } |
| 9289 |
| 9290 @override |
| 9291 void visitChildren(ElementVisitor visitor) { |
| 9292 super.visitChildren(visitor); |
| 9293 safelyVisitChildren(_parameters, visitor); |
| 9294 } |
| 9295 |
| 9296 @override |
| 9297 void appendTo(JavaStringBuilder builder) { |
| 9298 String left = ""; |
| 9299 String right = ""; |
| 9300 while (true) { |
| 9301 if (parameterKind == ParameterKind.NAMED) { |
| 9302 left = "{"; |
| 9303 right = "}"; |
| 9304 } else if (parameterKind == ParameterKind.POSITIONAL) { |
| 9305 left = "["; |
| 9306 right = "]"; |
| 9307 } else if (parameterKind == ParameterKind.REQUIRED) { |
| 9308 } |
| 9309 break; |
| 9310 } |
| 9311 builder.append(left); |
| 9312 appendToWithoutDelimiters(builder); |
| 9313 builder.append(right); |
| 9314 } |
| 9315 |
| 9316 /** |
| 9317 * Append the type and name of this parameter to the given builder. |
| 9318 * |
| 9319 * @param builder the builder to which the type and name are to be appended |
| 9320 */ |
| 9321 void appendToWithoutDelimiters(JavaStringBuilder builder) { |
| 9322 builder.append(type); |
| 9323 builder.append(" "); |
| 9324 builder.append(displayName); |
| 9325 } |
| 9326 } |
| 9327 |
| 9328 /** |
| 9329 * Instances of the class `ParameterMember` represent a parameter element define
d in a |
| 9330 * parameterized type where the values of the type parameters are known. |
| 9331 */ |
| 9332 class ParameterMember extends VariableMember implements ParameterElement { |
| 9333 /** |
| 9334 * If the given parameter's type is different when any type parameters from th
e defining type's |
| 9335 * declaration are replaced with the actual type arguments from the defining t
ype, create a |
| 9336 * parameter member representing the given parameter. Return the member that w
as created, or the |
| 9337 * base parameter if no member was created. |
| 9338 * |
| 9339 * @param baseParameter the base parameter for which a member might be created |
| 9340 * @param definingType the type defining the parameters and arguments to be us
ed in the |
| 9341 * substitution |
| 9342 * @return the parameter element that will return the correctly substituted ty
pes |
| 9343 */ |
| 9344 static ParameterElement from(ParameterElement baseParameter, ParameterizedType
definingType) { |
| 9345 if (baseParameter == null || definingType.typeArguments.length == 0) { |
| 9346 return baseParameter; |
| 9347 } |
| 9348 // Check if parameter type depends on defining type type arguments. |
| 9349 // It is possible that we did not resolve field formal parameter yet, so ski
p this check for it. |
| 9350 bool isFieldFormal = baseParameter is FieldFormalParameterElement; |
| 9351 if (!isFieldFormal) { |
| 9352 DartType baseType = baseParameter.type; |
| 9353 List<DartType> argumentTypes = definingType.typeArguments; |
| 9354 List<DartType> parameterTypes = TypeParameterTypeImpl.getTypes(definingTyp
e.typeParameters); |
| 9355 DartType substitutedType = baseType.substitute2(argumentTypes, parameterTy
pes); |
| 9356 if (baseType == substitutedType) { |
| 9357 return baseParameter; |
| 9358 } |
| 9359 } |
| 9360 // TODO(brianwilkerson) Consider caching the substituted type in the instanc
e. It would use more |
| 9361 // memory but speed up some operations. We need to see how often the type is
being re-computed. |
| 9362 if (isFieldFormal) { |
| 9363 return new FieldFormalParameterMember(baseParameter as FieldFormalParamete
rElement, definingType); |
| 9364 } |
| 9365 return new ParameterMember(baseParameter, definingType); |
| 9366 } |
| 9367 |
| 9368 /** |
| 9369 * Initialize a newly created element to represent a parameter of the given pa
rameterized type. |
| 9370 * |
| 9371 * @param baseElement the element on which the parameterized element was creat
ed |
| 9372 * @param definingType the type in which the element is defined |
| 9373 */ |
| 9374 ParameterMember(ParameterElement baseElement, ParameterizedType definingType)
: super(baseElement, definingType); |
| 9375 |
| 9376 @override |
| 9377 accept(ElementVisitor visitor) => visitor.visitParameterElement(this); |
| 9378 |
| 9379 @override |
| 9380 Element getAncestor(Predicate<Element> predicate) { |
| 9381 Element element = baseElement.getAncestor(predicate); |
| 9382 ParameterizedType definingType = this.definingType; |
| 9383 if (definingType is InterfaceType) { |
| 9384 InterfaceType definingInterfaceType = definingType; |
| 9385 if (element is ConstructorElement) { |
| 9386 return ConstructorMember.from(element, definingInterfaceType); |
| 9387 } else if (element is MethodElement) { |
| 9388 return MethodMember.from(element, definingInterfaceType); |
| 9389 } else if (element is PropertyAccessorElement) { |
| 9390 return PropertyAccessorMember.from(element, definingInterfaceType); |
| 9391 } |
| 9392 } |
| 9393 return element; |
| 9394 } |
| 9395 |
| 9396 @override |
| 9397 ParameterElement get baseElement => super.baseElement as ParameterElement; |
| 9398 |
| 9399 @override |
| 9400 SourceRange get defaultValueRange => baseElement.defaultValueRange; |
| 9401 |
| 9402 @override |
| 9403 Element get enclosingElement => baseElement.enclosingElement; |
| 9404 |
| 9405 @override |
| 9406 ParameterKind get parameterKind => baseElement.parameterKind; |
| 9407 |
| 9408 @override |
| 9409 List<ParameterElement> get parameters { |
| 9410 List<ParameterElement> baseParameters = baseElement.parameters; |
| 9411 int parameterCount = baseParameters.length; |
| 9412 if (parameterCount == 0) { |
| 9413 return baseParameters; |
| 9414 } |
| 9415 List<ParameterElement> parameterizedParameters = new List<ParameterElement>(
parameterCount); |
| 9416 for (int i = 0; i < parameterCount; i++) { |
| 9417 parameterizedParameters[i] = ParameterMember.from(baseParameters[i], defin
ingType); |
| 9418 } |
| 9419 return parameterizedParameters; |
| 9420 } |
| 9421 |
| 9422 @override |
| 9423 SourceRange get visibleRange => baseElement.visibleRange; |
| 9424 |
| 9425 @override |
| 9426 bool get isInitializingFormal => baseElement.isInitializingFormal; |
| 9427 |
| 9428 @override |
| 9429 String toString() { |
| 9430 ParameterElement baseElement = this.baseElement; |
| 9431 String left = ""; |
| 9432 String right = ""; |
| 9433 while (true) { |
| 9434 if (baseElement.parameterKind == ParameterKind.NAMED) { |
| 9435 left = "{"; |
| 9436 right = "}"; |
| 9437 } else if (baseElement.parameterKind == ParameterKind.POSITIONAL) { |
| 9438 left = "["; |
| 9439 right = "]"; |
| 9440 } else if (baseElement.parameterKind == ParameterKind.REQUIRED) { |
| 9441 } |
| 9442 break; |
| 9443 } |
| 9444 JavaStringBuilder builder = new JavaStringBuilder(); |
| 9445 builder.append(left); |
| 9446 builder.append(type); |
| 9447 builder.append(" "); |
| 9448 builder.append(baseElement.displayName); |
| 9449 builder.append(right); |
| 9450 return builder.toString(); |
| 9451 } |
| 9452 |
| 9453 @override |
| 9454 void visitChildren(ElementVisitor visitor) { |
| 9455 super.visitChildren(visitor); |
| 9456 safelyVisitChildren(parameters, visitor); |
| 9457 } |
| 9458 } |
| 9459 |
| 9460 /** |
| 9461 * The interface `ParameterizedType` defines the behavior common to objects repr
esenting a |
| 9462 * type with type parameters, such as a class or function type alias. |
| 9463 */ |
| 9464 abstract class ParameterizedType implements DartType { |
| 9465 /** |
| 9466 * Return an array containing the actual types of the type arguments. If this
type's element does |
| 9467 * not have type parameters, then the array should be empty (although it is po
ssible for type |
| 9468 * arguments to be erroneously declared). If the element has type parameters a
nd the actual type |
| 9469 * does not explicitly include argument values, then the type "dynamic" will b
e automatically |
| 9470 * provided. |
| 9471 * |
| 9472 * @return the actual types of the type arguments |
| 9473 */ |
| 9474 List<DartType> get typeArguments; |
| 9475 |
| 9476 /** |
| 9477 * Return an array containing all of the type parameters declared for this typ
e. |
| 9478 * |
| 9479 * @return the type parameters declared for this type |
| 9480 */ |
| 9481 List<TypeParameterElement> get typeParameters; |
| 9482 } |
| 9483 |
| 9484 /** |
| 9485 * The interface `PolymerAttributeElement` defines an attribute in |
| 9486 * [PolymerTagHtmlElement]. |
| 9487 * |
| 9488 * <pre> |
| 9489 * <polymer-element name="my-example" attributes='attrA attrB'> |
| 9490 * </polymer-element> |
| 9491 * </pre> |
| 9492 */ |
| 9493 abstract class PolymerAttributeElement implements PolymerElement { |
| 9494 /** |
| 9495 * An empty array of Polymer custom tag attributes. |
| 9496 */ |
| 9497 static final List<PolymerAttributeElement> EMPTY_ARRAY = new List<PolymerAttri
buteElement>(0); |
| 9498 |
| 9499 /** |
| 9500 * Return the [FieldElement] associated with this attribute. Maybe `null` if |
| 9501 * [PolymerTagDartElement] does not have a field associated with it. |
| 9502 */ |
| 9503 FieldElement get field; |
| 9504 } |
| 9505 |
| 9506 /** |
| 9507 * Implementation of `PolymerAttributeElement`. |
| 9508 */ |
| 9509 class PolymerAttributeElementImpl extends PolymerElementImpl implements PolymerA
ttributeElement { |
| 9510 /** |
| 9511 * The [FieldElement] associated with this attribute. |
| 9512 */ |
| 9513 FieldElement field; |
| 9514 |
| 9515 /** |
| 9516 * Initialize a newly created Polymer attribute to have the given name. |
| 9517 * |
| 9518 * @param name the name of this element |
| 9519 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 9520 * declaration of this element |
| 9521 */ |
| 9522 PolymerAttributeElementImpl(String name, int nameOffset) : super(name, nameOff
set); |
| 9523 |
| 9524 @override |
| 9525 accept(ElementVisitor visitor) => visitor.visitPolymerAttributeElement(this); |
| 9526 |
| 9527 @override |
| 9528 ElementKind get kind => ElementKind.POLYMER_ATTRIBUTE; |
| 9529 } |
| 9530 |
| 9531 /** |
| 9532 * The interface `PolymerElement` defines the behavior of objects representing i
nformation |
| 9533 * about a Polymer specific element. |
| 9534 */ |
| 9535 abstract class PolymerElement implements ToolkitObjectElement { |
| 9536 /** |
| 9537 * An empty array of Polymer elements. |
| 9538 */ |
| 9539 static final List<PolymerElement> EMPTY_ARRAY = new List<PolymerElement>(0); |
| 9540 } |
| 9541 |
| 9542 /** |
| 9543 * Implementation of `PolymerElement`. |
| 9544 */ |
| 9545 abstract class PolymerElementImpl extends ToolkitObjectElementImpl implements Po
lymerElement { |
| 9546 /** |
| 9547 * Initialize a newly created Polymer element to have the given name. |
| 9548 * |
| 9549 * @param name the name of this element |
| 9550 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 9551 * declaration of this element |
| 9552 */ |
| 9553 PolymerElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 9554 } |
| 9555 |
| 9556 /** |
| 9557 * The interface `PolymerTagDartElement` defines a Polymer custom tag in Dart. |
| 9558 * |
| 9559 * <pre> |
| 9560 * @CustomTag('my-example') |
| 9561 * </pre> |
| 9562 */ |
| 9563 abstract class PolymerTagDartElement implements PolymerElement { |
| 9564 /** |
| 9565 * Return the [ClassElement] that is associated with this Polymer custom tag.
Not |
| 9566 * `null`, because [PolymerTagDartElement]s are created for [ClassElement]s |
| 9567 * marked with the `@CustomTag` annotation. |
| 9568 */ |
| 9569 ClassElement get classElement; |
| 9570 |
| 9571 /** |
| 9572 * Return the [PolymerTagHtmlElement] part of this Polymer custom tag. Maybe `
null` if |
| 9573 * it has not been resolved yet or there are no corresponding Dart part define
d. |
| 9574 */ |
| 9575 PolymerTagHtmlElement get htmlElement; |
| 9576 } |
| 9577 |
| 9578 /** |
| 9579 * Implementation of `PolymerTagDartElement`. |
| 9580 */ |
| 9581 class PolymerTagDartElementImpl extends PolymerElementImpl implements PolymerTag
DartElement { |
| 9582 /** |
| 9583 * The [ClassElement] that is associated with this Polymer custom tag. |
| 9584 */ |
| 9585 final ClassElement classElement; |
| 9586 |
| 9587 /** |
| 9588 * The [PolymerTagHtmlElement] part of this Polymer custom tag. Maybe `null` i
f it has |
| 9589 * not been resolved yet or there are no corresponding Dart part defined. |
| 9590 */ |
| 9591 PolymerTagHtmlElement htmlElement; |
| 9592 |
| 9593 /** |
| 9594 * Initialize a newly created Dart part of a Polymer tag to have the given nam
e. |
| 9595 * |
| 9596 * @param name the name of this element |
| 9597 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 9598 * declaration of this element |
| 9599 */ |
| 9600 PolymerTagDartElementImpl(String name, int nameOffset, this.classElement) : su
per(name, nameOffset); |
| 9601 |
| 9602 @override |
| 9603 accept(ElementVisitor visitor) => visitor.visitPolymerTagDartElement(this); |
| 9604 |
| 9605 @override |
| 9606 ElementKind get kind => ElementKind.POLYMER_TAG_DART; |
| 9607 } |
| 9608 |
| 9609 /** |
| 9610 * The interface `PolymerTagHtmlElement` defines a Polymer custom tag in HTML. |
| 9611 * |
| 9612 * <pre> |
| 9613 * <polymer-element name="my-example" attributes='attrA attrB'> |
| 9614 * </polymer-element> |
| 9615 * </pre> |
| 9616 */ |
| 9617 abstract class PolymerTagHtmlElement implements PolymerElement { |
| 9618 /** |
| 9619 * An empty array of [PolymerTagHtmlElement]s. |
| 9620 */ |
| 9621 static final List<PolymerTagHtmlElement> EMPTY_ARRAY = new List<PolymerTagHtml
Element>(0); |
| 9622 |
| 9623 /** |
| 9624 * Return an array containing all of the attributes declared by this tag. |
| 9625 */ |
| 9626 List<PolymerAttributeElement> get attributes; |
| 9627 |
| 9628 /** |
| 9629 * Return the [PolymerTagDartElement] part on this Polymer custom tag. Maybe `
null` if |
| 9630 * it has not been resolved yet or there are no corresponding Dart part define
d. |
| 9631 */ |
| 9632 PolymerTagDartElement get dartElement; |
| 9633 } |
| 9634 |
| 9635 /** |
| 9636 * Implementation of `PolymerTagHtmlElement`. |
| 9637 */ |
| 9638 class PolymerTagHtmlElementImpl extends PolymerElementImpl implements PolymerTag
HtmlElement { |
| 9639 /** |
| 9640 * The [PolymerTagDartElement] part of this Polymer custom tag. Maybe `null` i
f it has |
| 9641 * not been resolved yet or there are no corresponding Dart part defined. |
| 9642 */ |
| 9643 PolymerTagDartElement dartElement; |
| 9644 |
| 9645 /** |
| 9646 * The array containing all of the attributes declared by this tag. |
| 9647 */ |
| 9648 List<PolymerAttributeElement> _attributes = PolymerAttributeElement.EMPTY_ARRA
Y; |
| 9649 |
| 9650 /** |
| 9651 * Initialize a newly created HTML part of a Polymer tag to have the given nam
e. |
| 9652 * |
| 9653 * @param name the name of this element |
| 9654 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 9655 * declaration of this element |
| 9656 */ |
| 9657 PolymerTagHtmlElementImpl(String name, int nameOffset) : super(name, nameOffse
t); |
| 9658 |
| 9659 @override |
| 9660 accept(ElementVisitor visitor) => visitor.visitPolymerTagHtmlElement(this); |
| 9661 |
| 9662 @override |
| 9663 List<PolymerAttributeElement> get attributes => _attributes; |
| 9664 |
| 9665 @override |
| 9666 ElementKind get kind => ElementKind.POLYMER_TAG_HTML; |
| 9667 |
| 9668 /** |
| 9669 * Set an array containing all of the attributes declared by this tag. |
| 9670 * |
| 9671 * @param attributes the properties to set |
| 9672 */ |
| 9673 void set attributes(List<PolymerAttributeElement> attributes) { |
| 9674 for (PolymerAttributeElement property in attributes) { |
| 9675 encloseElement(property as PolymerAttributeElementImpl); |
| 9676 } |
| 9677 this._attributes = attributes; |
| 9678 } |
| 9679 |
| 9680 @override |
| 9681 void visitChildren(ElementVisitor visitor) { |
| 9682 safelyVisitChildren(_attributes, visitor); |
| 9683 super.visitChildren(visitor); |
| 9684 } |
| 9685 } |
| 9686 |
| 9687 /** |
| 9688 * The interface `PrefixElement` defines the behavior common to elements that re
present a |
| 9689 * prefix used to import one or more libraries into another library. |
| 9690 */ |
| 9691 abstract class PrefixElement implements Element { |
| 9692 /** |
| 9693 * Return the library into which other libraries are imported using this prefi
x. |
| 9694 * |
| 9695 * @return the library into which other libraries are imported using this pref
ix |
| 9696 */ |
| 9697 @override |
| 9698 LibraryElement get enclosingElement; |
| 9699 |
| 9700 /** |
| 9701 * Return an array containing all of the libraries that are imported using thi
s prefix. |
| 9702 * |
| 9703 * @return the libraries that are imported using this prefix |
| 9704 */ |
| 9705 List<LibraryElement> get importedLibraries; |
| 9706 } |
| 9707 |
| 9708 /** |
| 9709 * Instances of the class `PrefixElementImpl` implement a `PrefixElement`. |
| 9710 */ |
| 9711 class PrefixElementImpl extends ElementImpl implements PrefixElement { |
| 9712 /** |
| 9713 * An array containing all of the libraries that are imported using this prefi
x. |
| 9714 */ |
| 9715 List<LibraryElement> _importedLibraries = LibraryElementImpl.EMPTY_ARRAY; |
| 9716 |
| 9717 /** |
| 9718 * An empty array of prefix elements. |
| 9719 */ |
| 9720 static List<PrefixElement> EMPTY_ARRAY = new List<PrefixElement>(0); |
| 9721 |
| 9722 /** |
| 9723 * Initialize a newly created prefix element to have the given name. |
| 9724 * |
| 9725 * @param name the name of this element |
| 9726 */ |
| 9727 PrefixElementImpl.forNode(Identifier name) : super.forNode(name); |
| 9728 |
| 9729 /** |
| 9730 * Initialize a newly created method element to have the given name. |
| 9731 * |
| 9732 * @param name the name of this element |
| 9733 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 9734 * declaration of this element |
| 9735 */ |
| 9736 PrefixElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 9737 |
| 9738 @override |
| 9739 accept(ElementVisitor visitor) => visitor.visitPrefixElement(this); |
| 9740 |
| 9741 @override |
| 9742 LibraryElement get enclosingElement => super.enclosingElement as LibraryElemen
t; |
| 9743 |
| 9744 @override |
| 9745 List<LibraryElement> get importedLibraries => _importedLibraries; |
| 9746 |
| 9747 @override |
| 9748 ElementKind get kind => ElementKind.PREFIX; |
| 9749 |
| 9750 /** |
| 9751 * Set the libraries that are imported using this prefix to the given librarie
s. |
| 9752 * |
| 9753 * @param importedLibraries the libraries that are imported using this prefix |
| 9754 */ |
| 9755 void set importedLibraries(List<LibraryElement> importedLibraries) { |
| 9756 for (LibraryElement library in importedLibraries) { |
| 9757 (library as LibraryElementImpl).enclosingElement = this; |
| 9758 } |
| 9759 this._importedLibraries = importedLibraries; |
| 9760 } |
| 9761 |
| 9762 @override |
| 9763 void appendTo(JavaStringBuilder builder) { |
| 9764 builder.append("as "); |
| 9765 super.appendTo(builder); |
| 9766 } |
| 9767 |
| 9768 @override |
| 9769 String get identifier => "_${super.identifier}"; |
| 9770 } |
| 9771 |
| 9772 /** |
| 9773 * The interface `PropertyAccessorElement` defines the behavior of elements repr
esenting a |
| 9774 * getter or a setter. Note that explicitly defined property accessors implicitl
y define a synthetic |
| 9775 * field. Symmetrically, synthetic accessors are implicitly created for explicit
ly defined fields. |
| 9776 * The following rules apply: |
| 9777 * * Every explicit field is represented by a non-synthetic [FieldElement]. |
| 9778 * * Every explicit field induces a getter and possibly a setter, both of which
are represented by |
| 9779 * synthetic [PropertyAccessorElement]s. |
| 9780 * * Every explicit getter or setter is represented by a non-synthetic |
| 9781 * [PropertyAccessorElement]. |
| 9782 * * Every explicit getter or setter (or pair thereof if they have the same name
) induces a field |
| 9783 * that is represented by a synthetic [FieldElement]. |
| 9784 */ |
| 9785 abstract class PropertyAccessorElement implements ExecutableElement { |
| 9786 /** |
| 9787 * Return the accessor representing the getter that corresponds to (has the sa
me name as) this |
| 9788 * setter, or `null` if this accessor is not a setter or if there is no corres
ponding |
| 9789 * getter. |
| 9790 * |
| 9791 * @return the getter that corresponds to this setter |
| 9792 */ |
| 9793 PropertyAccessorElement get correspondingGetter; |
| 9794 |
| 9795 /** |
| 9796 * Return the accessor representing the setter that corresponds to (has the sa
me name as) this |
| 9797 * getter, or `null` if this accessor is not a getter or if there is no corres
ponding |
| 9798 * setter. |
| 9799 * |
| 9800 * @return the setter that corresponds to this getter |
| 9801 */ |
| 9802 PropertyAccessorElement get correspondingSetter; |
| 9803 |
| 9804 /** |
| 9805 * Return the field or top-level variable associated with this accessor. If th
is accessor was |
| 9806 * explicitly defined (is not synthetic) then the variable associated with it
will be synthetic. |
| 9807 * |
| 9808 * @return the variable associated with this accessor |
| 9809 */ |
| 9810 PropertyInducingElement get variable; |
| 9811 |
| 9812 /** |
| 9813 * Return `true` if this accessor is abstract. Accessors are abstract if they
are not |
| 9814 * external and have no body. |
| 9815 * |
| 9816 * @return `true` if this accessor is abstract |
| 9817 */ |
| 9818 bool get isAbstract; |
| 9819 |
| 9820 /** |
| 9821 * Return `true` if this accessor represents a getter. |
| 9822 * |
| 9823 * @return `true` if this accessor represents a getter |
| 9824 */ |
| 9825 bool get isGetter; |
| 9826 |
| 9827 /** |
| 9828 * Return `true` if this accessor represents a setter. |
| 9829 * |
| 9830 * @return `true` if this accessor represents a setter |
| 9831 */ |
| 9832 bool get isSetter; |
| 9833 } |
| 9834 |
| 9835 /** |
| 9836 * Instances of the class `PropertyAccessorElementImpl` implement a |
| 9837 * `PropertyAccessorElement`. |
| 9838 */ |
| 9839 class PropertyAccessorElementImpl extends ExecutableElementImpl implements Prope
rtyAccessorElement { |
| 9840 /** |
| 9841 * The variable associated with this accessor. |
| 9842 */ |
| 9843 PropertyInducingElement variable; |
| 9844 |
| 9845 /** |
| 9846 * An empty array of property accessor elements. |
| 9847 */ |
| 9848 static List<PropertyAccessorElement> EMPTY_ARRAY = new List<PropertyAccessorEl
ement>(0); |
| 9849 |
| 9850 /** |
| 9851 * Initialize a newly created property accessor element to have the given name
. |
| 9852 * |
| 9853 * @param name the name of this element |
| 9854 */ |
| 9855 PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name); |
| 9856 |
| 9857 /** |
| 9858 * Initialize a newly created synthetic property accessor element to be associ
ated with the given |
| 9859 * variable. |
| 9860 * |
| 9861 * @param variable the variable with which this access is associated |
| 9862 */ |
| 9863 PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable)
: super(variable.name, variable.nameOffset) { |
| 9864 this.variable = variable; |
| 9865 static = variable.isStatic; |
| 9866 synthetic = true; |
| 9867 } |
| 9868 |
| 9869 @override |
| 9870 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this); |
| 9871 |
| 9872 @override |
| 9873 bool operator ==(Object object) => super == object && isGetter == (object as P
ropertyAccessorElement).isGetter; |
| 9874 |
| 9875 @override |
| 9876 PropertyAccessorElement get correspondingGetter { |
| 9877 if (isGetter || variable == null) { |
| 9878 return null; |
| 9879 } |
| 9880 return variable.getter; |
| 9881 } |
| 9882 |
| 9883 @override |
| 9884 PropertyAccessorElement get correspondingSetter { |
| 9885 if (isSetter || variable == null) { |
| 9886 return null; |
| 9887 } |
| 9888 return variable.setter; |
| 9889 } |
| 9890 |
| 9891 @override |
| 9892 ElementKind get kind { |
| 9893 if (isGetter) { |
| 9894 return ElementKind.GETTER; |
| 9895 } |
| 9896 return ElementKind.SETTER; |
| 9897 } |
| 9898 |
| 9899 @override |
| 9900 String get name { |
| 9901 if (isSetter) { |
| 9902 return "${super.name}="; |
| 9903 } |
| 9904 return super.name; |
| 9905 } |
| 9906 |
| 9907 @override |
| 9908 AstNode get node { |
| 9909 if (isSynthetic) { |
| 9910 return null; |
| 9911 } |
| 9912 if (enclosingElement is ClassElement) { |
| 9913 return getNodeMatching((node) => node is MethodDeclaration); |
| 9914 } |
| 9915 if (enclosingElement is CompilationUnitElement) { |
| 9916 return getNodeMatching((node) => node is FunctionDeclaration); |
| 9917 } |
| 9918 return null; |
| 9919 } |
| 9920 |
| 9921 @override |
| 9922 int get hashCode => ObjectUtilities.combineHashCodes(super.hashCode, isGetter
? 1 : 2); |
| 9923 |
| 9924 @override |
| 9925 bool get isAbstract => hasModifier(Modifier.ABSTRACT); |
| 9926 |
| 9927 @override |
| 9928 bool get isGetter => hasModifier(Modifier.GETTER); |
| 9929 |
| 9930 @override |
| 9931 bool get isSetter => hasModifier(Modifier.SETTER); |
| 9932 |
| 9933 @override |
| 9934 bool get isStatic => hasModifier(Modifier.STATIC); |
| 9935 |
| 9936 /** |
| 9937 * Set whether this accessor is abstract to correspond to the given value. |
| 9938 * |
| 9939 * @param isAbstract `true` if the accessor is abstract |
| 9940 */ |
| 9941 void set abstract(bool isAbstract) { |
| 9942 setModifier(Modifier.ABSTRACT, isAbstract); |
| 9943 } |
| 9944 |
| 9945 /** |
| 9946 * Set whether this accessor is a getter to correspond to the given value. |
| 9947 * |
| 9948 * @param isGetter `true` if the accessor is a getter |
| 9949 */ |
| 9950 void set getter(bool isGetter) { |
| 9951 setModifier(Modifier.GETTER, isGetter); |
| 9952 } |
| 9953 |
| 9954 /** |
| 9955 * Set whether this accessor is a setter to correspond to the given value. |
| 9956 * |
| 9957 * @param isSetter `true` if the accessor is a setter |
| 9958 */ |
| 9959 void set setter(bool isSetter) { |
| 9960 setModifier(Modifier.SETTER, isSetter); |
| 9961 } |
| 9962 |
| 9963 /** |
| 9964 * Set whether this accessor is static to correspond to the given value. |
| 9965 * |
| 9966 * @param isStatic `true` if the accessor is static |
| 9967 */ |
| 9968 void set static(bool isStatic) { |
| 9969 setModifier(Modifier.STATIC, isStatic); |
| 9970 } |
| 9971 |
| 9972 @override |
| 9973 void appendTo(JavaStringBuilder builder) { |
| 9974 builder.append(isGetter ? "get " : "set "); |
| 9975 builder.append(variable.displayName); |
| 9976 super.appendTo(builder); |
| 9977 } |
| 9978 |
| 9979 @override |
| 9980 String get identifier { |
| 9981 String name = displayName; |
| 9982 String suffix = isGetter ? "?" : "="; |
| 9983 return "${name}${suffix}"; |
| 9984 } |
| 9985 } |
| 9986 |
| 9987 /** |
| 9988 * Instances of the class `PropertyAccessorMember` represent a property accessor
element |
| 9989 * defined in a parameterized type where the values of the type parameters are k
nown. |
| 9990 */ |
| 9991 class PropertyAccessorMember extends ExecutableMember implements PropertyAccesso
rElement { |
| 9992 /** |
| 9993 * If the given property accessor's type is different when any type parameters
from the defining |
| 9994 * type's declaration are replaced with the actual type arguments from the def
ining type, create a |
| 9995 * property accessor member representing the given property accessor. Return t
he member that was |
| 9996 * created, or the base accessor if no member was created. |
| 9997 * |
| 9998 * @param baseAccessor the base property accessor for which a member might be
created |
| 9999 * @param definingType the type defining the parameters and arguments to be us
ed in the |
| 10000 * substitution |
| 10001 * @return the property accessor element that will return the correctly substi
tuted types |
| 10002 */ |
| 10003 static PropertyAccessorElement from(PropertyAccessorElement baseAccessor, Inte
rfaceType definingType) { |
| 10004 if (!_isChangedByTypeSubstitution(baseAccessor, definingType)) { |
| 10005 return baseAccessor; |
| 10006 } |
| 10007 // TODO(brianwilkerson) Consider caching the substituted type in the instanc
e. It would use more |
| 10008 // memory but speed up some operations. We need to see how often the type is
being re-computed. |
| 10009 return new PropertyAccessorMember(baseAccessor, definingType); |
| 10010 } |
| 10011 |
| 10012 /** |
| 10013 * Determine whether the given property accessor's type is changed when type p
arameters from the |
| 10014 * defining type's declaration are replaced with the actual type arguments fro
m the defining type. |
| 10015 * |
| 10016 * @param baseAccessor the base property accessor |
| 10017 * @param definingType the type defining the parameters and arguments to be us
ed in the |
| 10018 * substitution |
| 10019 * @return true if the type is changed by type substitution. |
| 10020 */ |
| 10021 static bool _isChangedByTypeSubstitution(PropertyAccessorElement baseAccessor,
InterfaceType definingType) { |
| 10022 List<DartType> argumentTypes = definingType.typeArguments; |
| 10023 if (baseAccessor != null && argumentTypes.length != 0) { |
| 10024 FunctionType baseType = baseAccessor.type; |
| 10025 List<DartType> parameterTypes = definingType.element.type.typeArguments; |
| 10026 FunctionType substitutedType = baseType.substitute2(argumentTypes, paramet
erTypes); |
| 10027 if (baseType != substitutedType) { |
| 10028 return true; |
| 10029 } |
| 10030 // If this property accessor is based on a field, that field might have a
propagated type. |
| 10031 // In which case we need to check whether the propagated type of the field
needs substitution. |
| 10032 PropertyInducingElement field = baseAccessor.variable; |
| 10033 if (!field.isSynthetic) { |
| 10034 DartType baseFieldType = field.propagatedType; |
| 10035 if (baseFieldType != null) { |
| 10036 DartType substitutedFieldType = baseFieldType.substitute2(argumentType
s, parameterTypes); |
| 10037 if (baseFieldType != substitutedFieldType) { |
| 10038 return true; |
| 10039 } |
| 10040 } |
| 10041 } |
| 10042 } |
| 10043 return false; |
| 10044 } |
| 10045 |
| 10046 /** |
| 10047 * Initialize a newly created element to represent a property accessor of the
given parameterized |
| 10048 * type. |
| 10049 * |
| 10050 * @param baseElement the element on which the parameterized element was creat
ed |
| 10051 * @param definingType the type in which the element is defined |
| 10052 */ |
| 10053 PropertyAccessorMember(PropertyAccessorElement baseElement, InterfaceType defi
ningType) : super(baseElement, definingType); |
| 10054 |
| 10055 @override |
| 10056 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this); |
| 10057 |
| 10058 @override |
| 10059 PropertyAccessorElement get baseElement => super.baseElement as PropertyAccess
orElement; |
| 10060 |
| 10061 @override |
| 10062 PropertyAccessorElement get correspondingGetter => from(baseElement.correspond
ingGetter, definingType); |
| 10063 |
| 10064 @override |
| 10065 PropertyAccessorElement get correspondingSetter => from(baseElement.correspond
ingSetter, definingType); |
| 10066 |
| 10067 @override |
| 10068 Element get enclosingElement => baseElement.enclosingElement; |
| 10069 |
| 10070 @override |
| 10071 PropertyInducingElement get variable { |
| 10072 PropertyInducingElement variable = baseElement.variable; |
| 10073 if (variable is FieldElement) { |
| 10074 return FieldMember.from(variable, definingType); |
| 10075 } |
| 10076 return variable; |
| 10077 } |
| 10078 |
| 10079 @override |
| 10080 bool get isAbstract => baseElement.isAbstract; |
| 10081 |
| 10082 @override |
| 10083 bool get isGetter => baseElement.isGetter; |
| 10084 |
| 10085 @override |
| 10086 bool get isSetter => baseElement.isSetter; |
| 10087 |
| 10088 @override |
| 10089 String toString() { |
| 10090 PropertyAccessorElement baseElement = this.baseElement; |
| 10091 List<ParameterElement> parameters = this.parameters; |
| 10092 FunctionType type = this.type; |
| 10093 JavaStringBuilder builder = new JavaStringBuilder(); |
| 10094 if (isGetter) { |
| 10095 builder.append("get "); |
| 10096 } else { |
| 10097 builder.append("set "); |
| 10098 } |
| 10099 builder.append(baseElement.enclosingElement.displayName); |
| 10100 builder.append("."); |
| 10101 builder.append(baseElement.displayName); |
| 10102 builder.append("("); |
| 10103 int parameterCount = parameters.length; |
| 10104 for (int i = 0; i < parameterCount; i++) { |
| 10105 if (i > 0) { |
| 10106 builder.append(", "); |
| 10107 } |
| 10108 builder.append(parameters[i]).toString(); |
| 10109 } |
| 10110 builder.append(")"); |
| 10111 if (type != null) { |
| 10112 builder.append(Element.RIGHT_ARROW); |
| 10113 builder.append(type.returnType); |
| 10114 } |
| 10115 return builder.toString(); |
| 10116 } |
| 10117 |
| 10118 @override |
| 10119 InterfaceType get definingType => super.definingType as InterfaceType; |
| 10120 } |
| 10121 |
| 10122 /** |
| 10123 * The interface `PropertyInducingElement` defines the behavior of elements repr
esenting a |
| 10124 * variable that has an associated getter and possibly a setter. Note that expli
citly defined |
| 10125 * variables implicitly define a synthetic getter and that non-`final` explicitl
y defined |
| 10126 * variables implicitly define a synthetic setter. Symmetrically, synthetic fiel
ds are implicitly |
| 10127 * created for explicitly defined getters and setters. The following rules apply
: |
| 10128 * * Every explicit variable is represented by a non-synthetic [PropertyInducing
Element]. |
| 10129 * * Every explicit variable induces a getter and possibly a setter, both of whi
ch are represented |
| 10130 * by synthetic [PropertyAccessorElement]s. |
| 10131 * * Every explicit getter or setter is represented by a non-synthetic |
| 10132 * [PropertyAccessorElement]. |
| 10133 * * Every explicit getter or setter (or pair thereof if they have the same name
) induces a |
| 10134 * variable that is represented by a synthetic [PropertyInducingElement]. |
| 10135 */ |
| 10136 abstract class PropertyInducingElement implements VariableElement { |
| 10137 /** |
| 10138 * Return the getter associated with this variable. If this variable was expli
citly defined (is |
| 10139 * not synthetic) then the getter associated with it will be synthetic. |
| 10140 * |
| 10141 * @return the getter associated with this variable |
| 10142 */ |
| 10143 PropertyAccessorElement get getter; |
| 10144 |
| 10145 /** |
| 10146 * Return the propagated type of this variable, or `null` if type propagation
has not been |
| 10147 * performed, for example because the variable is not final. |
| 10148 * |
| 10149 * @return the propagated type of this variable |
| 10150 */ |
| 10151 DartType get propagatedType; |
| 10152 |
| 10153 /** |
| 10154 * Return the setter associated with this variable, or `null` if the variable
is effectively |
| 10155 * `final` and therefore does not have a setter associated with it. (This can
happen either |
| 10156 * because the variable is explicitly defined as being `final` or because the
variable is |
| 10157 * induced by an explicit getter that does not have a corresponding setter.) I
f this variable was |
| 10158 * explicitly defined (is not synthetic) then the setter associated with it wi
ll be synthetic. |
| 10159 * |
| 10160 * @return the setter associated with this variable |
| 10161 */ |
| 10162 PropertyAccessorElement get setter; |
| 10163 |
| 10164 /** |
| 10165 * Return `true` if this element is a static element. A static element is an e
lement that is |
| 10166 * not associated with a particular instance, but rather with an entire librar
y or class. |
| 10167 * |
| 10168 * @return `true` if this executable element is a static element |
| 10169 */ |
| 10170 bool get isStatic; |
| 10171 } |
| 10172 |
| 10173 /** |
| 10174 * Instances of the class `PropertyInducingElementImpl` implement a |
| 10175 * `PropertyInducingElement`. |
| 10176 */ |
| 10177 abstract class PropertyInducingElementImpl extends VariableElementImpl implement
s PropertyInducingElement { |
| 10178 /** |
| 10179 * The getter associated with this element. |
| 10180 */ |
| 10181 PropertyAccessorElement getter; |
| 10182 |
| 10183 /** |
| 10184 * The setter associated with this element, or `null` if the element is effect
ively |
| 10185 * `final` and therefore does not have a setter associated with it. |
| 10186 */ |
| 10187 PropertyAccessorElement setter; |
| 10188 |
| 10189 /** |
| 10190 * The propagated type of this variable, or `null` if type propagation has not
been |
| 10191 * performed. |
| 10192 */ |
| 10193 DartType propagatedType; |
| 10194 |
| 10195 /** |
| 10196 * An empty array of elements. |
| 10197 */ |
| 10198 static List<PropertyInducingElement> EMPTY_ARRAY = new List<PropertyInducingEl
ement>(0); |
| 10199 |
| 10200 /** |
| 10201 * Initialize a newly created element to have the given name. |
| 10202 * |
| 10203 * @param name the name of this element |
| 10204 */ |
| 10205 PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name); |
| 10206 |
| 10207 /** |
| 10208 * Initialize a newly created synthetic element to have the given name. |
| 10209 * |
| 10210 * @param name the name of this element |
| 10211 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 10212 * declaration of this element |
| 10213 */ |
| 10214 PropertyInducingElementImpl(String name, int nameOffset) : super(name, nameOff
set); |
| 10215 } |
| 10216 |
| 10217 /** |
| 10218 * Instances of the class `RecursiveElementVisitor` implement an element visitor
that will |
| 10219 * recursively visit all of the element in an element model. For example, using
an instance of this |
| 10220 * class to visit a [CompilationUnitElement] will also cause all of the types in
the |
| 10221 * compilation unit to be visited. |
| 10222 * |
| 10223 * Subclasses that override a visit method must either invoke the overridden vis
it method or must |
| 10224 * explicitly ask the visited element to visit its children. Failure to do so wi
ll cause the |
| 10225 * children of the visited element to not be visited. |
| 10226 */ |
| 10227 class RecursiveElementVisitor<R> implements ElementVisitor<R> { |
| 10228 @override |
| 10229 R visitAngularComponentElement(AngularComponentElement element) { |
| 10230 element.visitChildren(this); |
| 10231 return null; |
| 10232 } |
| 10233 |
| 10234 @override |
| 10235 R visitAngularControllerElement(AngularControllerElement element) { |
| 10236 element.visitChildren(this); |
| 10237 return null; |
| 10238 } |
| 10239 |
| 10240 @override |
| 10241 R visitAngularDirectiveElement(AngularDecoratorElement element) { |
| 10242 element.visitChildren(this); |
| 10243 return null; |
| 10244 } |
| 10245 |
| 10246 @override |
| 10247 R visitAngularFormatterElement(AngularFormatterElement element) { |
| 10248 element.visitChildren(this); |
| 10249 return null; |
| 10250 } |
| 10251 |
| 10252 @override |
| 10253 R visitAngularPropertyElement(AngularPropertyElement element) { |
| 10254 element.visitChildren(this); |
| 10255 return null; |
| 10256 } |
| 10257 |
| 10258 @override |
| 10259 R visitAngularScopePropertyElement(AngularScopePropertyElement element) { |
| 10260 element.visitChildren(this); |
| 10261 return null; |
| 10262 } |
| 10263 |
| 10264 @override |
| 10265 R visitAngularSelectorElement(AngularSelectorElement element) { |
| 10266 element.visitChildren(this); |
| 10267 return null; |
| 10268 } |
| 10269 |
| 10270 @override |
| 10271 R visitAngularViewElement(AngularViewElement element) { |
| 10272 element.visitChildren(this); |
| 10273 return null; |
| 10274 } |
| 10275 |
| 10276 @override |
| 10277 R visitClassElement(ClassElement element) { |
| 10278 element.visitChildren(this); |
| 10279 return null; |
| 10280 } |
| 10281 |
| 10282 @override |
| 10283 R visitCompilationUnitElement(CompilationUnitElement element) { |
| 10284 element.visitChildren(this); |
| 10285 return null; |
| 10286 } |
| 10287 |
| 10288 @override |
| 10289 R visitConstructorElement(ConstructorElement element) { |
| 10290 element.visitChildren(this); |
| 10291 return null; |
| 10292 } |
| 10293 |
| 10294 @override |
| 10295 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) { |
| 10296 element.visitChildren(this); |
| 10297 return null; |
| 10298 } |
| 10299 |
| 10300 @override |
| 10301 R visitExportElement(ExportElement element) { |
| 10302 element.visitChildren(this); |
| 10303 return null; |
| 10304 } |
| 10305 |
| 10306 @override |
| 10307 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) { |
| 10308 element.visitChildren(this); |
| 10309 return null; |
| 10310 } |
| 10311 |
| 10312 @override |
| 10313 R visitFieldElement(FieldElement element) { |
| 10314 element.visitChildren(this); |
| 10315 return null; |
| 10316 } |
| 10317 |
| 10318 @override |
| 10319 R visitFieldFormalParameterElement(FieldFormalParameterElement element) { |
| 10320 element.visitChildren(this); |
| 10321 return null; |
| 10322 } |
| 10323 |
| 10324 @override |
| 10325 R visitFunctionElement(FunctionElement element) { |
| 10326 element.visitChildren(this); |
| 10327 return null; |
| 10328 } |
| 10329 |
| 10330 @override |
| 10331 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { |
| 10332 element.visitChildren(this); |
| 10333 return null; |
| 10334 } |
| 10335 |
| 10336 @override |
| 10337 R visitHtmlElement(HtmlElement element) { |
| 10338 element.visitChildren(this); |
| 10339 return null; |
| 10340 } |
| 10341 |
| 10342 @override |
| 10343 R visitImportElement(ImportElement element) { |
| 10344 element.visitChildren(this); |
| 10345 return null; |
| 10346 } |
| 10347 |
| 10348 @override |
| 10349 R visitLabelElement(LabelElement element) { |
| 10350 element.visitChildren(this); |
| 10351 return null; |
| 10352 } |
| 10353 |
| 10354 @override |
| 10355 R visitLibraryElement(LibraryElement element) { |
| 10356 element.visitChildren(this); |
| 10357 return null; |
| 10358 } |
| 10359 |
| 10360 @override |
| 10361 R visitLocalVariableElement(LocalVariableElement element) { |
| 10362 element.visitChildren(this); |
| 10363 return null; |
| 10364 } |
| 10365 |
| 10366 @override |
| 10367 R visitMethodElement(MethodElement element) { |
| 10368 element.visitChildren(this); |
| 10369 return null; |
| 10370 } |
| 10371 |
| 10372 @override |
| 10373 R visitMultiplyDefinedElement(MultiplyDefinedElement element) { |
| 10374 element.visitChildren(this); |
| 10375 return null; |
| 10376 } |
| 10377 |
| 10378 @override |
| 10379 R visitParameterElement(ParameterElement element) { |
| 10380 element.visitChildren(this); |
| 10381 return null; |
| 10382 } |
| 10383 |
| 10384 @override |
| 10385 R visitPolymerAttributeElement(PolymerAttributeElement element) { |
| 10386 element.visitChildren(this); |
| 10387 return null; |
| 10388 } |
| 10389 |
| 10390 @override |
| 10391 R visitPolymerTagDartElement(PolymerTagDartElement element) { |
| 10392 element.visitChildren(this); |
| 10393 return null; |
| 10394 } |
| 10395 |
| 10396 @override |
| 10397 R visitPolymerTagHtmlElement(PolymerTagHtmlElement element) { |
| 10398 element.visitChildren(this); |
| 10399 return null; |
| 10400 } |
| 10401 |
| 10402 @override |
| 10403 R visitPrefixElement(PrefixElement element) { |
| 10404 element.visitChildren(this); |
| 10405 return null; |
| 10406 } |
| 10407 |
| 10408 @override |
| 10409 R visitPropertyAccessorElement(PropertyAccessorElement element) { |
| 10410 element.visitChildren(this); |
| 10411 return null; |
| 10412 } |
| 10413 |
| 10414 @override |
| 10415 R visitTopLevelVariableElement(TopLevelVariableElement element) { |
| 10416 element.visitChildren(this); |
| 10417 return null; |
| 10418 } |
| 10419 |
| 10420 @override |
| 10421 R visitTypeParameterElement(TypeParameterElement element) { |
| 10422 element.visitChildren(this); |
| 10423 return null; |
| 10424 } |
| 10425 } |
| 10426 |
| 10427 /** |
| 10428 * The interface `ShowElementCombinator` defines the behavior of combinators tha
t cause some |
| 10429 * of the names in a namespace to be visible (and the rest hidden) when being im
ported. |
| 10430 */ |
| 10431 abstract class ShowElementCombinator implements NamespaceCombinator { |
| 10432 /** |
| 10433 * Return the offset of the character immediately following the last character
of this node. |
| 10434 * |
| 10435 * @return the offset of the character just past this node |
| 10436 */ |
| 10437 int get end; |
| 10438 |
| 10439 /** |
| 10440 * Return the offset of the 'show' keyword of this element. |
| 10441 * |
| 10442 * @return the offset of the 'show' keyword of this element |
| 10443 */ |
| 10444 int get offset; |
| 10445 |
| 10446 /** |
| 10447 * Return an array containing the names that are to be made visible in the imp
orting library if |
| 10448 * they are defined in the imported library. |
| 10449 * |
| 10450 * @return the names from the imported library that are visible in the importi
ng library |
| 10451 */ |
| 10452 List<String> get shownNames; |
| 10453 } |
| 10454 |
| 10455 /** |
| 10456 * Instances of the class `ShowElementCombinatorImpl` implement a |
| 10457 * [ShowElementCombinator]. |
| 10458 */ |
| 10459 class ShowElementCombinatorImpl implements ShowElementCombinator { |
| 10460 /** |
| 10461 * The names that are to be made visible in the importing library if they are
defined in the |
| 10462 * imported library. |
| 10463 */ |
| 10464 List<String> shownNames = StringUtilities.EMPTY_ARRAY; |
| 10465 |
| 10466 /** |
| 10467 * The offset of the character immediately following the last character of thi
s node. |
| 10468 */ |
| 10469 int end = -1; |
| 10470 |
| 10471 /** |
| 10472 * The offset of the 'show' keyword of this element. |
| 10473 */ |
| 10474 int offset = 0; |
| 10475 |
| 10476 @override |
| 10477 String toString() { |
| 10478 JavaStringBuilder builder = new JavaStringBuilder(); |
| 10479 builder.append("show "); |
| 10480 int count = shownNames.length; |
| 10481 for (int i = 0; i < count; i++) { |
| 10482 if (i > 0) { |
| 10483 builder.append(", "); |
| 10484 } |
| 10485 builder.append(shownNames[i]); |
| 10486 } |
| 10487 return builder.toString(); |
| 10488 } |
| 10489 } |
| 10490 |
| 10491 /** |
| 10492 * Instances of the class `SimpleElementVisitor` implement an element visitor th
at will do |
| 10493 * nothing when visiting an element. It is intended to be a superclass for class
es that use the |
| 10494 * visitor pattern primarily as a dispatch mechanism (and hence don't need to re
cursively visit a |
| 10495 * whole structure) and that only need to visit a small number of element types. |
| 10496 */ |
| 10497 class SimpleElementVisitor<R> implements ElementVisitor<R> { |
| 10498 @override |
| 10499 R visitAngularComponentElement(AngularComponentElement element) => null; |
| 10500 |
| 10501 @override |
| 10502 R visitAngularControllerElement(AngularControllerElement element) => null; |
| 10503 |
| 10504 @override |
| 10505 R visitAngularDirectiveElement(AngularDecoratorElement element) => null; |
| 10506 |
| 10507 @override |
| 10508 R visitAngularFormatterElement(AngularFormatterElement element) => null; |
| 10509 |
| 10510 @override |
| 10511 R visitAngularPropertyElement(AngularPropertyElement element) => null; |
| 10512 |
| 10513 @override |
| 10514 R visitAngularScopePropertyElement(AngularScopePropertyElement element) => nul
l; |
| 10515 |
| 10516 @override |
| 10517 R visitAngularSelectorElement(AngularSelectorElement element) => null; |
| 10518 |
| 10519 @override |
| 10520 R visitAngularViewElement(AngularViewElement element) => null; |
| 10521 |
| 10522 @override |
| 10523 R visitClassElement(ClassElement element) => null; |
| 10524 |
| 10525 @override |
| 10526 R visitCompilationUnitElement(CompilationUnitElement element) => null; |
| 10527 |
| 10528 @override |
| 10529 R visitConstructorElement(ConstructorElement element) => null; |
| 10530 |
| 10531 @override |
| 10532 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => null; |
| 10533 |
| 10534 @override |
| 10535 R visitExportElement(ExportElement element) => null; |
| 10536 |
| 10537 @override |
| 10538 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => null; |
| 10539 |
| 10540 @override |
| 10541 R visitFieldElement(FieldElement element) => null; |
| 10542 |
| 10543 @override |
| 10544 R visitFieldFormalParameterElement(FieldFormalParameterElement element) => nul
l; |
| 10545 |
| 10546 @override |
| 10547 R visitFunctionElement(FunctionElement element) => null; |
| 10548 |
| 10549 @override |
| 10550 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => null; |
| 10551 |
| 10552 @override |
| 10553 R visitHtmlElement(HtmlElement element) => null; |
| 10554 |
| 10555 @override |
| 10556 R visitImportElement(ImportElement element) => null; |
| 10557 |
| 10558 @override |
| 10559 R visitLabelElement(LabelElement element) => null; |
| 10560 |
| 10561 @override |
| 10562 R visitLibraryElement(LibraryElement element) => null; |
| 10563 |
| 10564 @override |
| 10565 R visitLocalVariableElement(LocalVariableElement element) => null; |
| 10566 |
| 10567 @override |
| 10568 R visitMethodElement(MethodElement element) => null; |
| 10569 |
| 10570 @override |
| 10571 R visitMultiplyDefinedElement(MultiplyDefinedElement element) => null; |
| 10572 |
| 10573 @override |
| 10574 R visitParameterElement(ParameterElement element) => null; |
| 10575 |
| 10576 @override |
| 10577 R visitPolymerAttributeElement(PolymerAttributeElement element) => null; |
| 10578 |
| 10579 @override |
| 10580 R visitPolymerTagDartElement(PolymerTagDartElement element) => null; |
| 10581 |
| 10582 @override |
| 10583 R visitPolymerTagHtmlElement(PolymerTagHtmlElement element) => null; |
| 10584 |
| 10585 @override |
| 10586 R visitPrefixElement(PrefixElement element) => null; |
| 10587 |
| 10588 @override |
| 10589 R visitPropertyAccessorElement(PropertyAccessorElement element) => null; |
| 10590 |
| 10591 @override |
| 10592 R visitTopLevelVariableElement(TopLevelVariableElement element) => null; |
| 10593 |
| 10594 @override |
| 10595 R visitTypeParameterElement(TypeParameterElement element) => null; |
| 10596 } |
| 10597 |
| 10598 /** |
| 10599 * The interface `ToolkitObjectElement` defines the behavior of elements that re
present a |
| 10600 * toolkit specific object, such as Angular controller or component. These eleme
nts are not based on |
| 10601 * the Dart syntax, but on some semantic agreement, such as a special annotation
. |
| 10602 */ |
| 10603 abstract class ToolkitObjectElement implements Element { |
| 10604 /** |
| 10605 * An empty array of toolkit object elements. |
| 10606 */ |
| 10607 static final List<ToolkitObjectElement> EMPTY_ARRAY = new List<ToolkitObjectEl
ement>(0); |
| 10608 } |
| 10609 |
| 10610 /** |
| 10611 * Instances of the class `ToolkitObjectElementImpl` implement a `ToolkitObjectE
lement`. |
| 10612 */ |
| 10613 abstract class ToolkitObjectElementImpl extends ElementImpl implements ToolkitOb
jectElement { |
| 10614 /** |
| 10615 * Initialize a newly created toolkit object element to have the given name. |
| 10616 * |
| 10617 * @param name the name of this element |
| 10618 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 10619 * declaration of this element |
| 10620 */ |
| 10621 ToolkitObjectElementImpl(String name, int nameOffset) : super(name, nameOffset
); |
| 10622 } |
| 10623 |
| 10624 /** |
| 10625 * The interface `TopLevelVariableElement` defines the behavior of elements repr
esenting a |
| 10626 * top-level variable. |
| 10627 */ |
| 10628 abstract class TopLevelVariableElement implements PropertyInducingElement { |
| 10629 } |
| 10630 |
| 10631 /** |
| 10632 * Instances of the class `TopLevelVariableElementImpl` implement a |
| 10633 * `TopLevelVariableElement`. |
| 10634 */ |
| 10635 class TopLevelVariableElementImpl extends PropertyInducingElementImpl implements
TopLevelVariableElement { |
| 10636 /** |
| 10637 * An empty array of top-level variable elements. |
| 10638 */ |
| 10639 static List<TopLevelVariableElement> EMPTY_ARRAY = new List<TopLevelVariableEl
ement>(0); |
| 10640 |
| 10641 /** |
| 10642 * Initialize a newly created top-level variable element to have the given nam
e. |
| 10643 * |
| 10644 * @param name the name of this element |
| 10645 */ |
| 10646 TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name); |
| 10647 |
| 10648 /** |
| 10649 * Initialize a newly created synthetic top-level variable element to have the
given name. |
| 10650 * |
| 10651 * @param name the name of this element |
| 10652 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 10653 * declaration of this element |
| 10654 */ |
| 10655 TopLevelVariableElementImpl(String name, int nameOffset) : super(name, nameOff
set); |
| 10656 |
| 10657 @override |
| 10658 accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this); |
| 10659 |
| 10660 @override |
| 10661 ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE; |
| 10662 |
| 10663 @override |
| 10664 bool get isStatic => true; |
| 10665 } |
| 10666 |
| 10667 /** |
| 10668 * The abstract class `TypeImpl` implements the behavior common to objects repre
senting the |
| 10669 * declared type of elements in the element model. |
| 10670 */ |
| 10671 abstract class TypeImpl implements DartType { |
| 10672 static bool equalArrays(List<DartType> typeArgs1, List<DartType> typeArgs2, Se
t<ElementPair> visitedElementPairs) { |
| 10673 if (typeArgs1.length != typeArgs2.length) { |
| 10674 return false; |
| 10675 } |
| 10676 for (int i = 0; i < typeArgs1.length; i++) { |
| 10677 if (!(typeArgs1[i] as TypeImpl).internalEquals(typeArgs2[i], visitedElemen
tPairs)) { |
| 10678 return false; |
| 10679 } |
| 10680 } |
| 10681 return true; |
| 10682 } |
| 10683 |
| 10684 /** |
| 10685 * Return an array containing the results of using the given argument types an
d parameter types to |
| 10686 * perform a substitution on all of the given types. |
| 10687 * |
| 10688 * @param types the types on which a substitution is to be performed |
| 10689 * @param argumentTypes the argument types for the substitution |
| 10690 * @param parameterTypes the parameter types for the substitution |
| 10691 * @return the result of performing the substitution on each of the types |
| 10692 */ |
| 10693 static List<DartType> substitute(List<DartType> types, List<DartType> argument
Types, List<DartType> parameterTypes) { |
| 10694 int length = types.length; |
| 10695 if (length == 0) { |
| 10696 return types; |
| 10697 } |
| 10698 List<DartType> newTypes = new List<DartType>(length); |
| 10699 for (int i = 0; i < length; i++) { |
| 10700 newTypes[i] = types[i].substitute2(argumentTypes, parameterTypes); |
| 10701 } |
| 10702 return newTypes; |
| 10703 } |
| 10704 |
| 10705 /** |
| 10706 * The element representing the declaration of this type, or `null` if the typ
e has not, or |
| 10707 * cannot, be associated with an element. |
| 10708 */ |
| 10709 final Element _element; |
| 10710 |
| 10711 /** |
| 10712 * The name of this type, or `null` if the type does not have a name. |
| 10713 */ |
| 10714 final String name; |
| 10715 |
| 10716 /** |
| 10717 * An empty array of types. |
| 10718 */ |
| 10719 static List<DartType> EMPTY_ARRAY = new List<DartType>(0); |
| 10720 |
| 10721 /** |
| 10722 * Initialize a newly created type to be declared by the given element and to
have the given name. |
| 10723 * |
| 10724 * @param element the element representing the declaration of the type |
| 10725 * @param name the name of the type |
| 10726 */ |
| 10727 TypeImpl(this._element, this.name); |
| 10728 |
| 10729 @override |
| 10730 String get displayName => name; |
| 10731 |
| 10732 @override |
| 10733 Element get element => _element; |
| 10734 |
| 10735 @override |
| 10736 DartType getLeastUpperBound(DartType type) => null; |
| 10737 |
| 10738 @override |
| 10739 bool isAssignableTo(DartType type) => isAssignableTo2(type, new HashSet<TypeIm
pl_TypePair>()); |
| 10740 |
| 10741 /** |
| 10742 * Return `true` if this type is assignable to the given type. A type <i>T</i>
may be |
| 10743 * assigned to a type <i>S</i>, written <i>T</i> ⇔ <i>S</i>, iff either <
i>T</i> <: <i>S</i> |
| 10744 * or <i>S</i> <: <i>T</i> (Interface Types section of spec). |
| 10745 * |
| 10746 * The given set of pairs of types (T1, T2), where each pair indicates that we
invoked this method |
| 10747 * because we are in the process of answering the question of whether T1 is a
subtype of T2, is |
| 10748 * used to prevent infinite loops. |
| 10749 * |
| 10750 * @param type the type being compared with this type |
| 10751 * @param visitedTypePairs the set of pairs of types used to prevent infinite
loops |
| 10752 * @return `true` if this type is assignable to the given type |
| 10753 */ |
| 10754 bool isAssignableTo2(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) =
> isSubtypeOf2(type, visitedTypePairs) || (type as TypeImpl).isSubtypeOf2(this,
visitedTypePairs); |
| 10755 |
| 10756 @override |
| 10757 bool get isBottom => false; |
| 10758 |
| 10759 @override |
| 10760 bool get isDartCoreFunction => false; |
| 10761 |
| 10762 @override |
| 10763 bool get isDynamic => false; |
| 10764 |
| 10765 @override |
| 10766 bool isMoreSpecificThan(DartType type) => isMoreSpecificThan2(type, false, new
HashSet<TypeImpl_TypePair>()); |
| 10767 |
| 10768 /** |
| 10769 * Return `true` if this type is more specific than the given type. |
| 10770 * |
| 10771 * The given set of pairs of types (T1, T2), where each pair indicates that we
invoked this method |
| 10772 * because we are in the process of answering the question of whether T1 is a
subtype of T2, is |
| 10773 * used to prevent infinite loops. |
| 10774 * |
| 10775 * @param type the type being compared with this type |
| 10776 * @param withDynamic `true` if "dynamic" should be considered as a subtype of
any type |
| 10777 * @param visitedTypePairs the set of pairs of types used to prevent infinite
loops |
| 10778 * @return `true` if this type is more specific than the given type |
| 10779 */ |
| 10780 bool isMoreSpecificThan2(DartType type, bool withDynamic, Set<TypeImpl_TypePai
r> visitedTypePairs) { |
| 10781 // If the visitedTypePairs already has the pair (this, type), return false |
| 10782 TypeImpl_TypePair typePair = new TypeImpl_TypePair(this, type); |
| 10783 if (!visitedTypePairs.add(typePair)) { |
| 10784 return false; |
| 10785 } |
| 10786 bool result = internalIsMoreSpecificThan(type, withDynamic, visitedTypePairs
); |
| 10787 visitedTypePairs.remove(typePair); |
| 10788 return result; |
| 10789 } |
| 10790 |
| 10791 @override |
| 10792 bool get isObject => false; |
| 10793 |
| 10794 @override |
| 10795 bool isSubtypeOf(DartType type) => isSubtypeOf2(type, new HashSet<TypeImpl_Typ
ePair>()); |
| 10796 |
| 10797 /** |
| 10798 * Return `true` if this type is a subtype of the given type. |
| 10799 * |
| 10800 * The given set of pairs of types (T1, T2), where each pair indicates that we
invoked this method |
| 10801 * because we are in the process of answering the question of whether T1 is a
subtype of T2, is |
| 10802 * used to prevent infinite loops. |
| 10803 * |
| 10804 * @param type the type being compared with this type |
| 10805 * @param visitedTypePairs the set of pairs of types used to prevent infinite
loops |
| 10806 * @return `true` if this type is a subtype of the given type |
| 10807 */ |
| 10808 bool isSubtypeOf2(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) { |
| 10809 // If the visitedTypePairs already has the pair (this, type), return false |
| 10810 TypeImpl_TypePair typePair = new TypeImpl_TypePair(this, type); |
| 10811 if (!visitedTypePairs.add(typePair)) { |
| 10812 return false; |
| 10813 } |
| 10814 bool result = internalIsSubtypeOf(type, visitedTypePairs); |
| 10815 visitedTypePairs.remove(typePair); |
| 10816 return result; |
| 10817 } |
| 10818 |
| 10819 @override |
| 10820 bool isSupertypeOf(DartType type) => type.isSubtypeOf(this); |
| 10821 |
| 10822 @override |
| 10823 bool get isVoid => false; |
| 10824 |
| 10825 @override |
| 10826 String toString() { |
| 10827 JavaStringBuilder builder = new JavaStringBuilder(); |
| 10828 appendTo(builder); |
| 10829 return builder.toString(); |
| 10830 } |
| 10831 |
| 10832 /** |
| 10833 * Append a textual representation of this type to the given builder. |
| 10834 * |
| 10835 * @param builder the builder to which the text is to be appended |
| 10836 */ |
| 10837 void appendTo(JavaStringBuilder builder) { |
| 10838 if (name == null) { |
| 10839 builder.append("<unnamed type>"); |
| 10840 } else { |
| 10841 builder.append(name); |
| 10842 } |
| 10843 } |
| 10844 |
| 10845 bool internalEquals(Object object, Set<ElementPair> visitedElementPairs); |
| 10846 |
| 10847 bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_
TypePair> visitedTypePairs); |
| 10848 |
| 10849 bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePair
s); |
| 10850 } |
| 10851 |
| 10852 class TypeImpl_TypePair { |
| 10853 final DartType _firstType; |
| 10854 |
| 10855 final DartType _secondType; |
| 10856 |
| 10857 int _cachedHashCode = 0; |
| 10858 |
| 10859 TypeImpl_TypePair(this._firstType, this._secondType); |
| 10860 |
| 10861 @override |
| 10862 bool operator ==(Object object) { |
| 10863 if (identical(object, this)) { |
| 10864 return true; |
| 10865 } |
| 10866 if (object is TypeImpl_TypePair) { |
| 10867 TypeImpl_TypePair typePair = object; |
| 10868 return _firstType == typePair._firstType && _secondType != null && _second
Type == typePair._secondType; |
| 10869 } |
| 10870 return false; |
| 10871 } |
| 10872 |
| 10873 @override |
| 10874 int get hashCode { |
| 10875 if (_cachedHashCode == 0) { |
| 10876 int firstHashCode = 0; |
| 10877 if (_firstType != null) { |
| 10878 Element firstElement = _firstType.element; |
| 10879 firstHashCode = firstElement == null ? 0 : firstElement.hashCode; |
| 10880 } |
| 10881 int secondHashCode = 0; |
| 10882 if (_secondType != null) { |
| 10883 Element secondElement = _secondType.element; |
| 10884 secondHashCode = secondElement == null ? 0 : secondElement.hashCode; |
| 10885 } |
| 10886 _cachedHashCode = firstHashCode + secondHashCode; |
| 10887 } |
| 10888 return _cachedHashCode; |
| 10889 } |
| 10890 } |
| 10891 |
| 10892 /** |
| 10893 * The interface `TypeParameterElement` defines the behavior of elements represe
nting a type |
| 10894 * parameter. |
| 10895 */ |
| 10896 abstract class TypeParameterElement implements Element { |
| 10897 /** |
| 10898 * Return the type representing the bound associated with this parameter, or `
null` if this |
| 10899 * parameter does not have an explicit bound. |
| 10900 * |
| 10901 * @return the type representing the bound associated with this parameter |
| 10902 */ |
| 10903 DartType get bound; |
| 10904 |
| 10905 /** |
| 10906 * Return the type defined by this type parameter. |
| 10907 * |
| 10908 * @return the type defined by this type parameter |
| 10909 */ |
| 10910 TypeParameterType get type; |
| 10911 } |
| 10912 |
| 10913 /** |
| 10914 * Instances of the class `TypeParameterElementImpl` implement a [TypeParameterE
lement]. |
| 10915 */ |
| 10916 class TypeParameterElementImpl extends ElementImpl implements TypeParameterEleme
nt { |
| 10917 /** |
| 10918 * The type defined by this type parameter. |
| 10919 */ |
| 10920 TypeParameterType type; |
| 10921 |
| 10922 /** |
| 10923 * The type representing the bound associated with this parameter, or `null` i
f this |
| 10924 * parameter does not have an explicit bound. |
| 10925 */ |
| 10926 DartType bound; |
| 10927 |
| 10928 /** |
| 10929 * An empty array of type parameter elements. |
| 10930 */ |
| 10931 static List<TypeParameterElement> EMPTY_ARRAY = new List<TypeParameterElement>
(0); |
| 10932 |
| 10933 /** |
| 10934 * Initialize a newly created type parameter element to have the given name. |
| 10935 * |
| 10936 * @param name the name of this element |
| 10937 */ |
| 10938 TypeParameterElementImpl.forNode(Identifier name) : super.forNode(name); |
| 10939 |
| 10940 /** |
| 10941 * Initialize a newly created method element to have the given name. |
| 10942 * |
| 10943 * @param name the name of this element |
| 10944 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 10945 * declaration of this element |
| 10946 */ |
| 10947 TypeParameterElementImpl(String name, int nameOffset) : super(name, nameOffset
); |
| 10948 |
| 10949 @override |
| 10950 accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this); |
| 10951 |
| 10952 @override |
| 10953 ElementKind get kind => ElementKind.TYPE_PARAMETER; |
| 10954 |
| 10955 @override |
| 10956 void appendTo(JavaStringBuilder builder) { |
| 10957 builder.append(displayName); |
| 10958 if (bound != null) { |
| 10959 builder.append(" extends "); |
| 10960 builder.append(bound); |
| 10961 } |
| 10962 } |
| 10963 } |
| 10964 |
| 10965 /** |
| 10966 * The interface `TypeParameterType` defines the behavior of objects representin
g the type |
| 10967 * introduced by a type parameter. |
| 10968 */ |
| 10969 abstract class TypeParameterType implements DartType { |
| 10970 @override |
| 10971 TypeParameterElement get element; |
| 10972 } |
| 10973 |
| 10974 /** |
| 10975 * Instances of the class `TypeParameterTypeImpl` defines the behavior of object
s representing |
| 10976 * the type introduced by a type parameter. |
| 10977 */ |
| 10978 class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType { |
| 10979 /** |
| 10980 * An empty array of type parameter types. |
| 10981 */ |
| 10982 static List<TypeParameterType> EMPTY_ARRAY = new List<TypeParameterType>(0); |
| 10983 |
| 10984 /** |
| 10985 * Return an array containing the type parameter types defined by the given ar
ray of type |
| 10986 * parameter elements. |
| 10987 * |
| 10988 * @param typeParameters the type parameter elements defining the type paramet
er types to be |
| 10989 * returned |
| 10990 * @return the type parameter types defined by the type parameter elements |
| 10991 */ |
| 10992 static List<TypeParameterType> getTypes(List<TypeParameterElement> typeParamet
ers) { |
| 10993 int count = typeParameters.length; |
| 10994 if (count == 0) { |
| 10995 return EMPTY_ARRAY; |
| 10996 } |
| 10997 List<TypeParameterType> types = new List<TypeParameterType>(count); |
| 10998 for (int i = 0; i < count; i++) { |
| 10999 types[i] = typeParameters[i].type; |
| 11000 } |
| 11001 return types; |
| 11002 } |
| 11003 |
| 11004 /** |
| 11005 * Initialize a newly created type parameter type to be declared by the given
element and to have |
| 11006 * the given name. |
| 11007 * |
| 11008 * @param element the element representing the declaration of the type paramet
er |
| 11009 */ |
| 11010 TypeParameterTypeImpl(TypeParameterElement element) : super(element, element.n
ame); |
| 11011 |
| 11012 @override |
| 11013 bool operator ==(Object object) => object is TypeParameterTypeImpl && (element
== object.element); |
| 11014 |
| 11015 @override |
| 11016 TypeParameterElement get element => super.element as TypeParameterElement; |
| 11017 |
| 11018 @override |
| 11019 int get hashCode => element.hashCode; |
| 11020 |
| 11021 @override |
| 11022 DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTyp
es) { |
| 11023 int length = parameterTypes.length; |
| 11024 for (int i = 0; i < length; i++) { |
| 11025 if (parameterTypes[i] == this) { |
| 11026 return argumentTypes[i]; |
| 11027 } |
| 11028 } |
| 11029 return this; |
| 11030 } |
| 11031 |
| 11032 @override |
| 11033 bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => th
is == object; |
| 11034 |
| 11035 @override |
| 11036 bool internalIsMoreSpecificThan(DartType s, bool withDynamic, Set<TypeImpl_Typ
ePair> visitedTypePairs) { |
| 11037 // |
| 11038 // A type T is more specific than a type S, written T << S, if one of the f
ollowing conditions |
| 11039 // is met: |
| 11040 // |
| 11041 // Reflexivity: T is S. |
| 11042 // |
| 11043 if (this == s) { |
| 11044 return true; |
| 11045 } |
| 11046 // S is dynamic. |
| 11047 // |
| 11048 if (s.isDynamic) { |
| 11049 return true; |
| 11050 } |
| 11051 return _isMoreSpecificThan(s, new HashSet<DartType>(), withDynamic, visitedT
ypePairs); |
| 11052 } |
| 11053 |
| 11054 @override |
| 11055 bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePair
s) => isMoreSpecificThan2(type, true, new HashSet<TypeImpl_TypePair>()); |
| 11056 |
| 11057 bool _isMoreSpecificThan(DartType s, Set<DartType> visitedTypes, bool withDyna
mic, Set<TypeImpl_TypePair> visitedTypePairs) { |
| 11058 // |
| 11059 // T is a type parameter and S is the upper bound of T. |
| 11060 // |
| 11061 DartType bound = element.bound; |
| 11062 if (s == bound) { |
| 11063 return true; |
| 11064 } |
| 11065 // |
| 11066 // T is a type parameter and S is Object. |
| 11067 // |
| 11068 if (s.isObject) { |
| 11069 return true; |
| 11070 } |
| 11071 // We need upper bound to continue. |
| 11072 if (bound == null) { |
| 11073 return false; |
| 11074 } |
| 11075 // |
| 11076 // Transitivity: T << U and U << S. |
| 11077 // |
| 11078 if (bound is TypeParameterTypeImpl) { |
| 11079 TypeParameterTypeImpl boundTypeParameter = bound; |
| 11080 // First check for infinite loops |
| 11081 if (visitedTypes.contains(bound)) { |
| 11082 return false; |
| 11083 } |
| 11084 visitedTypes.add(bound); |
| 11085 // Then check upper bound. |
| 11086 return boundTypeParameter._isMoreSpecificThan(s, visitedTypes, withDynamic
, visitedTypePairs); |
| 11087 } |
| 11088 // Check interface type. |
| 11089 return (bound as TypeImpl).isMoreSpecificThan2(s, withDynamic, visitedTypePa
irs); |
| 11090 } |
| 11091 } |
| 11092 |
| 11093 /** |
| 11094 * The interface `UndefinedElement` defines the behavior of pseudo-elements that
represent |
| 11095 * names that are undefined. This situation is not allowed by the language, so o
bjects implementing |
| 11096 * this interface always represent an error. As a result, most of the normal ope
rations on elements |
| 11097 * do not make sense and will return useless results. |
| 11098 */ |
| 11099 abstract class UndefinedElement implements Element { |
| 11100 } |
| 11101 |
| 11102 /** |
| 11103 * A flat immutable union of `Type`s. Here "flat" means a union type never conta
ins another |
| 11104 * union type. |
| 11105 */ |
| 11106 abstract class UnionType implements DartType { |
| 11107 /** |
| 11108 * @return an immutable view of the types in this union type. |
| 11109 */ |
| 11110 Set<DartType> get elements; |
| 11111 } |
| 11112 |
| 11113 /** |
| 11114 * In addition to the methods of the `UnionType` interface we add a factory meth
od |
| 11115 * `union` for building unions. |
| 11116 */ |
| 11117 class UnionTypeImpl extends TypeImpl implements UnionType { |
| 11118 /** |
| 11119 * Any unions in the `types` will be flattened in the returned union. If there
is only one |
| 11120 * type after flattening then it will be returned directly, instead of a singl
eton union. |
| 11121 * |
| 11122 * @param types the `Type`s to union |
| 11123 * @return a `Type` comprising the `Type`s in `types` |
| 11124 */ |
| 11125 static DartType union(List<DartType> types) { |
| 11126 Set<DartType> set = new HashSet<DartType>(); |
| 11127 for (DartType t in types) { |
| 11128 if (t is UnionType) { |
| 11129 set.addAll(t.elements); |
| 11130 } else { |
| 11131 set.add(t); |
| 11132 } |
| 11133 } |
| 11134 if (set.length == 0) { |
| 11135 throw new IllegalArgumentException("No known use case for empty unions."); |
| 11136 } else if (set.length == 1) { |
| 11137 return new JavaIterator(set).next(); |
| 11138 } else { |
| 11139 return new UnionTypeImpl(set); |
| 11140 } |
| 11141 } |
| 11142 |
| 11143 /** |
| 11144 * The types in this union. |
| 11145 */ |
| 11146 final Set<DartType> _types; |
| 11147 |
| 11148 /** |
| 11149 * This constructor should only be called by the `union` factory: it does not
check that its |
| 11150 * argument `types` contains no union types. |
| 11151 * |
| 11152 * @param types |
| 11153 */ |
| 11154 UnionTypeImpl(this._types) : super(null, null); |
| 11155 |
| 11156 @override |
| 11157 bool operator ==(Object other) { |
| 11158 if (other == null || other is! UnionType) { |
| 11159 return false; |
| 11160 } else if (identical(this, other)) { |
| 11161 return true; |
| 11162 } else { |
| 11163 return javaSetEquals(_types, (other as UnionType).elements); |
| 11164 } |
| 11165 } |
| 11166 |
| 11167 @override |
| 11168 String get displayName { |
| 11169 JavaStringBuilder builder = new JavaStringBuilder(); |
| 11170 String prefix = "{"; |
| 11171 for (DartType t in _types) { |
| 11172 builder.append(prefix); |
| 11173 builder.append(t.displayName); |
| 11174 prefix = ","; |
| 11175 } |
| 11176 builder.append("}"); |
| 11177 return builder.toString(); |
| 11178 } |
| 11179 |
| 11180 @override |
| 11181 Set<DartType> get elements => _types; |
| 11182 |
| 11183 @override |
| 11184 int get hashCode => _types.hashCode; |
| 11185 |
| 11186 @override |
| 11187 DartType substitute2(List<DartType> argumentTypes, List<DartType> parameterTyp
es) { |
| 11188 List<DartType> out = new List<DartType>(); |
| 11189 for (DartType t in _types) { |
| 11190 out.add(t.substitute2(argumentTypes, parameterTypes)); |
| 11191 } |
| 11192 return union(new List.from(out)); |
| 11193 } |
| 11194 |
| 11195 @override |
| 11196 void appendTo(JavaStringBuilder builder) { |
| 11197 String prefix = "{"; |
| 11198 for (DartType t in _types) { |
| 11199 builder.append(prefix); |
| 11200 (t as TypeImpl).appendTo(builder); |
| 11201 prefix = ","; |
| 11202 } |
| 11203 builder.append("}"); |
| 11204 } |
| 11205 |
| 11206 @override |
| 11207 bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => th
is == object; |
| 11208 |
| 11209 @override |
| 11210 bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_
TypePair> visitedTypePairs) { |
| 11211 // TODO(collinsn): what version of subtyping do we want? |
| 11212 // |
| 11213 // The more unsound version: any. |
| 11214 /* |
| 11215 for (Type t : types) { |
| 11216 if (((TypeImpl) t).internalIsMoreSpecificThan(type, withDynamic, visitedTy
pePairs)) { |
| 11217 return true; |
| 11218 } |
| 11219 } |
| 11220 return false; |
| 11221 */ |
| 11222 // The less unsound version: all. |
| 11223 for (DartType t in _types) { |
| 11224 if (!(t as TypeImpl).internalIsMoreSpecificThan(type, withDynamic, visited
TypePairs)) { |
| 11225 return false; |
| 11226 } |
| 11227 } |
| 11228 return true; |
| 11229 } |
| 11230 |
| 11231 @override |
| 11232 bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePair
s) { |
| 11233 // TODO(collinsn): what version of subtyping do we want? |
| 11234 // |
| 11235 // The more unsound version: any. |
| 11236 /* |
| 11237 for (Type t : types) { |
| 11238 if (((TypeImpl) t).internalIsSubtypeOf(type, visitedTypePairs)) { |
| 11239 return true; |
| 11240 } |
| 11241 } |
| 11242 return false; |
| 11243 */ |
| 11244 // The less unsound version: all. |
| 11245 for (DartType t in _types) { |
| 11246 if (!(t as TypeImpl).internalIsSubtypeOf(type, visitedTypePairs)) { |
| 11247 return false; |
| 11248 } |
| 11249 } |
| 11250 return true; |
| 11251 } |
| 11252 |
| 11253 /** |
| 11254 * The more-specific-than test for union types on the RHS is uniform in non-un
ion LHSs. So, other |
| 11255 * `TypeImpl`s can call this method to implement `internalIsMoreSpecificThan`
for |
| 11256 * union types. |
| 11257 * |
| 11258 * @param type |
| 11259 * @param visitedTypePairs |
| 11260 * @return true if `type` is more specific than this union type |
| 11261 */ |
| 11262 bool internalUnionTypeIsMoreSpecificThan(DartType type, bool withDynamic, Set<
TypeImpl_TypePair> visitedTypePairs) { |
| 11263 // This implementation does not make sense when [type] is a union type, at l
east |
| 11264 // for the "less unsound" version of [internalIsMoreSpecificThan] above. |
| 11265 if (type is UnionType) { |
| 11266 throw new IllegalArgumentException("Only non-union types are supported."); |
| 11267 } |
| 11268 for (DartType t in _types) { |
| 11269 if ((type as TypeImpl).internalIsMoreSpecificThan(t, withDynamic, visitedT
ypePairs)) { |
| 11270 return true; |
| 11271 } |
| 11272 } |
| 11273 return false; |
| 11274 } |
| 11275 |
| 11276 /** |
| 11277 * The supertype test for union types is uniform in non-union subtypes. So, ot
her `TypeImpl` |
| 11278 * s can call this method to implement `internalIsSubtypeOf` for union types. |
| 11279 * |
| 11280 * @param type |
| 11281 * @param visitedTypePairs |
| 11282 * @return true if this union type is a super type of `type` |
| 11283 */ |
| 11284 bool internalUnionTypeIsSuperTypeOf(DartType type, Set<TypeImpl_TypePair> visi
tedTypePairs) { |
| 11285 // This implementation does not make sense when [type] is a union type, at l
east |
| 11286 // for the "less unsound" version of [internalIsSubtypeOf] above. |
| 11287 if (type is UnionType) { |
| 11288 throw new IllegalArgumentException("Only non-union types are supported."); |
| 11289 } |
| 11290 for (DartType t in _types) { |
| 11291 if ((type as TypeImpl).internalIsSubtypeOf(t, visitedTypePairs)) { |
| 11292 return true; |
| 11293 } |
| 11294 } |
| 11295 return false; |
| 11296 } |
| 11297 } |
| 11298 |
| 11299 /** |
| 11300 * The interface `UriReferencedElement` defines the behavior of objects included
into a |
| 11301 * library using some URI. |
| 11302 */ |
| 11303 abstract class UriReferencedElement implements Element { |
| 11304 /** |
| 11305 * Return the offset of the character immediately following the last character
of this node's URI, |
| 11306 * or `-1` for synthetic import. |
| 11307 * |
| 11308 * @return the offset of the character just past the node's URI |
| 11309 */ |
| 11310 int get uriEnd; |
| 11311 |
| 11312 /** |
| 11313 * Return the offset of the URI in the file, or `-1` if this element is synthe
tic. |
| 11314 * |
| 11315 * @return the offset of the URI |
| 11316 */ |
| 11317 int get uriOffset; |
| 11318 |
| 11319 /** |
| 11320 * Return the URI that is used to include this element into the enclosing libr
ary, or `null` |
| 11321 * if this is the defining compilation unit of a library. |
| 11322 * |
| 11323 * @return the URI that is used to include this element into the enclosing lib
rary |
| 11324 */ |
| 11325 String get uri; |
| 11326 } |
| 11327 |
| 11328 /** |
| 11329 * Instances of the class `UriReferencedElementImpl` implement an [UriReferenced
Element] |
| 11330 * . |
| 11331 */ |
| 11332 abstract class UriReferencedElementImpl extends ElementImpl implements UriRefere
ncedElement { |
| 11333 /** |
| 11334 * The offset of the URI in the file, may be `-1` if synthetic. |
| 11335 */ |
| 11336 int uriOffset = -1; |
| 11337 |
| 11338 /** |
| 11339 * The offset of the character immediately following the last character of thi
s node's URI, may be |
| 11340 * `-1` if synthetic. |
| 11341 */ |
| 11342 int uriEnd = -1; |
| 11343 |
| 11344 /** |
| 11345 * The URI that is specified by this directive. |
| 11346 */ |
| 11347 String uri; |
| 11348 |
| 11349 /** |
| 11350 * Initialize a newly created import element. |
| 11351 * |
| 11352 * @param name the name of this element |
| 11353 * @param offset the directive offset, may be `-1` if synthetic. |
| 11354 */ |
| 11355 UriReferencedElementImpl(String name, int offset) : super(name, offset); |
| 11356 } |
| 11357 |
| 11358 /** |
| 11359 * The interface `VariableElement` defines the behavior common to elements that
represent a |
| 11360 * variable. |
| 11361 */ |
| 11362 abstract class VariableElement implements Element { |
| 11363 /** |
| 11364 * Return a synthetic function representing this variable's initializer, or `n
ull` if this |
| 11365 * variable does not have an initializer. The function will have no parameters
. The return type of |
| 11366 * the function will be the compile-time type of the initialization expression
. |
| 11367 * |
| 11368 * @return a synthetic function representing this variable's initializer |
| 11369 */ |
| 11370 FunctionElement get initializer; |
| 11371 |
| 11372 /** |
| 11373 * Return the resolved [VariableDeclaration] node that declares this [Variable
Element] |
| 11374 * . |
| 11375 * |
| 11376 * This method is expensive, because resolved AST might be evicted from cache,
so parsing and |
| 11377 * resolving will be performed. |
| 11378 * |
| 11379 * @return the resolved [VariableDeclaration], not `null`. |
| 11380 */ |
| 11381 @override |
| 11382 VariableDeclaration get node; |
| 11383 |
| 11384 /** |
| 11385 * Return the declared type of this variable, or `null` if the variable did no
t have a |
| 11386 * declared type (such as if it was declared using the keyword 'var'). |
| 11387 * |
| 11388 * @return the declared type of this variable |
| 11389 */ |
| 11390 DartType get type; |
| 11391 |
| 11392 /** |
| 11393 * Return `true` if this variable was declared with the 'const' modifier. |
| 11394 * |
| 11395 * @return `true` if this variable was declared with the 'const' modifier |
| 11396 */ |
| 11397 bool get isConst; |
| 11398 |
| 11399 /** |
| 11400 * Return `true` if this variable was declared with the 'final' modifier. Vari
ables that are |
| 11401 * declared with the 'const' modifier will return `false` even though they are
implicitly |
| 11402 * final. |
| 11403 * |
| 11404 * @return `true` if this variable was declared with the 'final' modifier |
| 11405 */ |
| 11406 bool get isFinal; |
| 11407 } |
| 11408 |
| 11409 /** |
| 11410 * Instances of the class `VariableElementImpl` implement a `VariableElement`. |
| 11411 */ |
| 11412 abstract class VariableElementImpl extends ElementImpl implements VariableElemen
t { |
| 11413 /** |
| 11414 * The declared type of this variable. |
| 11415 */ |
| 11416 DartType type; |
| 11417 |
| 11418 /** |
| 11419 * A synthetic function representing this variable's initializer, or `null` if
this variable |
| 11420 * does not have an initializer. |
| 11421 */ |
| 11422 FunctionElement _initializer; |
| 11423 |
| 11424 /** |
| 11425 * An empty array of variable elements. |
| 11426 */ |
| 11427 static List<VariableElement> EMPTY_ARRAY = new List<VariableElement>(0); |
| 11428 |
| 11429 /** |
| 11430 * Initialize a newly created variable element to have the given name. |
| 11431 * |
| 11432 * @param name the name of this element |
| 11433 */ |
| 11434 VariableElementImpl.forNode(Identifier name) : super.forNode(name); |
| 11435 |
| 11436 /** |
| 11437 * Initialize a newly created variable element to have the given name. |
| 11438 * |
| 11439 * @param name the name of this element |
| 11440 * @param nameOffset the offset of the name of this element in the file that c
ontains the |
| 11441 * declaration of this element |
| 11442 */ |
| 11443 VariableElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 11444 |
| 11445 /** |
| 11446 * Return the result of evaluating this variable's initializer as a compile-ti
me constant |
| 11447 * expression, or `null` if this variable is not a 'const' variable, if it doe
s not have an |
| 11448 * initializer, or if the compilation unit containing the variable has not bee
n resolved. |
| 11449 * |
| 11450 * @return the result of evaluating this variable's initializer |
| 11451 */ |
| 11452 EvaluationResultImpl get evaluationResult => null; |
| 11453 |
| 11454 @override |
| 11455 FunctionElement get initializer => _initializer; |
| 11456 |
| 11457 @override |
| 11458 VariableDeclaration get node => getNodeMatching((node) => node is VariableDecl
aration); |
| 11459 |
| 11460 @override |
| 11461 bool get isConst => hasModifier(Modifier.CONST); |
| 11462 |
| 11463 @override |
| 11464 bool get isFinal => hasModifier(Modifier.FINAL); |
| 11465 |
| 11466 /** |
| 11467 * Return `true` if this variable is potentially mutated somewhere in a closur
e. This |
| 11468 * information is only available for local variables (including parameters) an
d only after the |
| 11469 * compilation unit containing the variable has been resolved. |
| 11470 * |
| 11471 * @return `true` if this variable is potentially mutated somewhere in closure |
| 11472 */ |
| 11473 bool get isPotentiallyMutatedInClosure => false; |
| 11474 |
| 11475 /** |
| 11476 * Return `true` if this variable is potentially mutated somewhere in its scop
e. This |
| 11477 * information is only available for local variables (including parameters) an
d only after the |
| 11478 * compilation unit containing the variable has been resolved. |
| 11479 * |
| 11480 * @return `true` if this variable is potentially mutated somewhere in its sco
pe |
| 11481 */ |
| 11482 bool get isPotentiallyMutatedInScope => false; |
| 11483 |
| 11484 /** |
| 11485 * Set whether this variable is const to correspond to the given value. |
| 11486 * |
| 11487 * @param isConst `true` if the variable is const |
| 11488 */ |
| 11489 void set const3(bool isConst) { |
| 11490 setModifier(Modifier.CONST, isConst); |
| 11491 } |
| 11492 |
| 11493 /** |
| 11494 * Set the result of evaluating this variable's initializer as a compile-time
constant expression |
| 11495 * to the given result. |
| 11496 * |
| 11497 * @param result the result of evaluating this variable's initializer |
| 11498 */ |
| 11499 void set evaluationResult(EvaluationResultImpl result) { |
| 11500 throw new IllegalStateException("Invalid attempt to set a compile-time const
ant result"); |
| 11501 } |
| 11502 |
| 11503 /** |
| 11504 * Set whether this variable is final to correspond to the given value. |
| 11505 * |
| 11506 * @param isFinal `true` if the variable is final |
| 11507 */ |
| 11508 void set final2(bool isFinal) { |
| 11509 setModifier(Modifier.FINAL, isFinal); |
| 11510 } |
| 11511 |
| 11512 /** |
| 11513 * Set the function representing this variable's initializer to the given func
tion. |
| 11514 * |
| 11515 * @param initializer the function representing this variable's initializer |
| 11516 */ |
| 11517 void set initializer(FunctionElement initializer) { |
| 11518 if (initializer != null) { |
| 11519 (initializer as FunctionElementImpl).enclosingElement = this; |
| 11520 } |
| 11521 this._initializer = initializer; |
| 11522 } |
| 11523 |
| 11524 @override |
| 11525 void visitChildren(ElementVisitor visitor) { |
| 11526 super.visitChildren(visitor); |
| 11527 safelyVisitChild(_initializer, visitor); |
| 11528 } |
| 11529 |
| 11530 @override |
| 11531 void appendTo(JavaStringBuilder builder) { |
| 11532 builder.append(type); |
| 11533 builder.append(" "); |
| 11534 builder.append(displayName); |
| 11535 } |
| 11536 } |
| 11537 |
| 11538 /** |
| 11539 * The abstract class `VariableMember` defines the behavior common to members th
at represent a |
| 11540 * variable element defined in a parameterized type where the values of the type
parameters are |
| 11541 * known. |
| 11542 */ |
| 11543 abstract class VariableMember extends Member implements VariableElement { |
| 11544 /** |
| 11545 * Initialize a newly created element to represent an executable element of th
e given |
| 11546 * parameterized type. |
| 11547 * |
| 11548 * @param baseElement the element on which the parameterized element was creat
ed |
| 11549 * @param definingType the type in which the element is defined |
| 11550 */ |
| 11551 VariableMember(VariableElement baseElement, ParameterizedType definingType) :
super(baseElement, definingType); |
| 11552 |
| 11553 @override |
| 11554 VariableElement get baseElement => super.baseElement as VariableElement; |
| 11555 |
| 11556 @override |
| 11557 FunctionElement get initializer { |
| 11558 // |
| 11559 // Elements within this element should have type parameters substituted, jus
t like this element. |
| 11560 // |
| 11561 throw new UnsupportedOperationException(); |
| 11562 } |
| 11563 |
| 11564 @override |
| 11565 VariableDeclaration get node => baseElement.node; |
| 11566 |
| 11567 @override |
| 11568 DartType get type => substituteFor(baseElement.type); |
| 11569 |
| 11570 @override |
| 11571 bool get isConst => baseElement.isConst; |
| 11572 |
| 11573 @override |
| 11574 bool get isFinal => baseElement.isFinal; |
| 11575 |
| 11576 @override |
| 11577 void visitChildren(ElementVisitor visitor) { |
| 11578 // TODO(brianwilkerson) We need to finish implementing the accessors used be
low so that we can |
| 11579 // safely invoke them. |
| 11580 super.visitChildren(visitor); |
| 11581 safelyVisitChild(baseElement.initializer, visitor); |
| 11582 } |
| 11583 } |
| 11584 |
| 11585 /** |
| 11586 * The interface `VoidType` defines the behavior of the unique object representi
ng the type |
| 11587 * `void`. |
| 11588 */ |
| 11589 abstract class VoidType implements DartType { |
| 11590 @override |
| 11591 VoidType substitute2(List<DartType> argumentTypes, List<DartType> parameterTyp
es); |
| 11592 } |
| 11593 |
| 11594 /** |
| 11595 * The unique instance of the class `VoidTypeImpl` implements the type `void`. |
| 11596 */ |
| 11597 class VoidTypeImpl extends TypeImpl implements VoidType { |
| 11598 /** |
| 11599 * The unique instance of this class. |
| 11600 */ |
| 11601 static VoidTypeImpl _INSTANCE = new VoidTypeImpl(); |
| 11602 |
| 11603 /** |
| 11604 * Return the unique instance of this class. |
| 11605 * |
| 11606 * @return the unique instance of this class |
| 11607 */ |
| 11608 static VoidTypeImpl get instance => _INSTANCE; |
| 11609 |
| 11610 /** |
| 11611 * Prevent the creation of instances of this class. |
| 11612 */ |
| 11613 VoidTypeImpl() : super(null, Keyword.VOID.syntax); |
| 11614 |
| 11615 @override |
| 11616 bool operator ==(Object object) => identical(object, this); |
| 11617 |
| 11618 @override |
| 11619 int get hashCode => 2; |
| 11620 |
| 11621 @override |
| 11622 bool get isVoid => true; |
| 11623 |
| 11624 @override |
| 11625 VoidTypeImpl substitute2(List<DartType> argumentTypes, List<DartType> paramete
rTypes) => this; |
| 11626 |
| 11627 @override |
| 11628 bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => id
entical(object, this); |
| 11629 |
| 11630 @override |
| 11631 bool internalIsMoreSpecificThan(DartType type, bool withDynamic, Set<TypeImpl_
TypePair> visitedTypePairs) => isSubtypeOf(type); |
| 11632 |
| 11633 @override |
| 11634 bool internalIsSubtypeOf(DartType type, Set<TypeImpl_TypePair> visitedTypePair
s) { |
| 11635 if (type is UnionType) { |
| 11636 return (type as UnionTypeImpl).internalUnionTypeIsSuperTypeOf(this, visite
dTypePairs); |
| 11637 } |
| 11638 // The only subtype relations that pertain to void are therefore: |
| 11639 // void <: void (by reflexivity) |
| 11640 // bottom <: void (as bottom is a subtype of all types). |
| 11641 // void <: dynamic (as dynamic is a supertype of all types) |
| 11642 return identical(type, this) || identical(type, DynamicTypeImpl.instance); |
| 11643 } |
| 11644 } |
OLD | NEW |