OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Datatypes holding information extracted by the analyzer and used by later | 6 * Datatypes holding information extracted by the analyzer and used by later |
7 * phases of the compiler. | 7 * phases of the compiler. |
8 */ | 8 */ |
9 library info; | 9 library info; |
10 | 10 |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 } | 287 } |
288 | 288 |
289 /** | 289 /** |
290 * True if [tagName] was defined by more than one component. If this happened | 290 * True if [tagName] was defined by more than one component. If this happened |
291 * we will skip over the component. | 291 * we will skip over the component. |
292 */ | 292 */ |
293 bool hasConflict = false; | 293 bool hasConflict = false; |
294 | 294 |
295 ComponentInfo(this.element, this.declaringFile, this.tagName, this.extendsTag, | 295 ComponentInfo(this.element, this.declaringFile, this.tagName, this.extendsTag, |
296 this.constructor, this.template); | 296 this.constructor, this.template); |
| 297 |
| 298 /** |
| 299 * Gets the HTML tag extended by the base of the component hierarchy. |
| 300 * Equivalent to [extendsTag] if this inherits directly from an HTML element, |
| 301 * in other words, if [extendsComponent] is null. |
| 302 */ |
| 303 String get baseExtendsTag => |
| 304 extendsComponent == null ? extendsTag : extendsComponent.baseExtendsTag; |
297 } | 305 } |
298 | 306 |
299 /** Base tree visitor for the Analyzer infos. */ | 307 /** Base tree visitor for the Analyzer infos. */ |
300 class InfoVisitor { | 308 class InfoVisitor { |
301 visit(info) { | 309 visit(info) { |
302 if (info == null) return; | 310 if (info == null) return; |
303 if (info is TemplateInfo) { | 311 if (info is TemplateInfo) { |
304 return visitTemplateInfo(info); | 312 return visitTemplateInfo(info); |
305 } else if (info is ElementInfo) { | 313 } else if (info is ElementInfo) { |
306 return visitElementInfo(info); | 314 return visitElementInfo(info); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 // preserve the order of the input, but we'd need to be careful about our tree | 404 // preserve the order of the input, but we'd need to be careful about our tree |
397 // traversal order. | 405 // traversal order. |
398 /** Collected information for attributes, if any. */ | 406 /** Collected information for attributes, if any. */ |
399 final Map<String, AttributeInfo> attributes = | 407 final Map<String, AttributeInfo> attributes = |
400 new SplayTreeMap<String, AttributeInfo>(); | 408 new SplayTreeMap<String, AttributeInfo>(); |
401 | 409 |
402 /** Collected information for UI events on the corresponding element. */ | 410 /** Collected information for UI events on the corresponding element. */ |
403 final Map<String, List<EventInfo>> events = | 411 final Map<String, List<EventInfo>> events = |
404 new SplayTreeMap<String, List<EventInfo>>(); | 412 new SplayTreeMap<String, List<EventInfo>>(); |
405 | 413 |
406 /** Collected information about `data-value="name:value"` expressions. */ | 414 /** |
| 415 * Collected information about `data-value="name:value"` expressions. |
| 416 * Note: this feature is deprecated and should be removed after grace period. |
| 417 */ |
407 final Map<String, String> values = new SplayTreeMap<String, String>(); | 418 final Map<String, String> values = new SplayTreeMap<String, String>(); |
408 | 419 |
409 // TODO(jmesserly): we could keep this local to the analyzer. | 420 // TODO(jmesserly): we could keep this local to the analyzer. |
410 /** Attribute names to remove in cleanup phase. */ | 421 /** Attribute names to remove in cleanup phase. */ |
411 final Set<String> removeAttributes = new Set<String>(); | 422 final Set<String> removeAttributes = new Set<String>(); |
412 | 423 |
413 /** Whether the template element has `iterate="... in ...". */ | 424 /** Whether the template element has `iterate="... in ...". */ |
414 bool get hasIterate => false; | 425 bool get hasIterate => false; |
415 | 426 |
416 /** Whether the template element has an `if="..."` conditional. */ | 427 /** Whether the template element has an `if="..."` conditional. */ |
417 bool get hasIfCondition => false; | 428 bool get hasIfCondition => false; |
418 | 429 |
419 bool get isTemplateElement => false; | 430 bool get isTemplateElement => false; |
420 | 431 |
| 432 /** |
| 433 * For a builtin HTML element this returns the [node.tagName], otherwise it |
| 434 * returns [component.baseExtendsTag]. This is useful when looking up which |
| 435 * DOM property this element supports. |
| 436 * |
| 437 * **Note:** this returns node.tagName right now, until we fix issue #82. |
| 438 */ |
| 439 String get baseTagName { |
| 440 return node.tagName; |
| 441 // TODO(jmesserly): turn this on when issue #82 is fixed. |
| 442 //return component != null ? component.baseExtendsTag : node.tagName; |
| 443 } |
| 444 |
421 ElementInfo(Element node, ElementInfo parent) : super(node, parent); | 445 ElementInfo(Element node, ElementInfo parent) : super(node, parent); |
422 | 446 |
423 String toString() => '#<ElementInfo ' | 447 String toString() => '#<ElementInfo ' |
424 'identifier: $identifier, ' | 448 'identifier: $identifier, ' |
425 'childrenCreatedInCode: $childrenCreatedInCode, ' | 449 'childrenCreatedInCode: $childrenCreatedInCode, ' |
426 'component: $component, ' | 450 'component: $component, ' |
427 'hasIterate: $hasIterate, ' | 451 'hasIterate: $hasIterate, ' |
428 'hasIfCondition: $hasIfCondition, ' | 452 'hasIfCondition: $hasIfCondition, ' |
429 'hasDataBinding: $hasDataBinding, ' | 453 'hasDataBinding: $hasDataBinding, ' |
430 'hasQuery: $hasQuery, ' | 454 'hasQuery: $hasQuery, ' |
(...skipping 27 matching lines...) Expand all Loading... |
458 | 482 |
459 /** | 483 /** |
460 * Whether this is a 'data-style' attribute. | 484 * Whether this is a 'data-style' attribute. |
461 */ | 485 */ |
462 final bool isStyle; | 486 final bool isStyle; |
463 | 487 |
464 /** All bound values that would be monitored for changes. */ | 488 /** All bound values that would be monitored for changes. */ |
465 final List<String> bindings; | 489 final List<String> bindings; |
466 | 490 |
467 /** | 491 /** |
| 492 * A two-way binding that needs a watcher. This is used in cases where we |
| 493 * don't have an event. |
| 494 */ |
| 495 final bool customTwoWayBinding; |
| 496 |
| 497 /** |
468 * For a text attribute this contains the text content. This is used by most | 498 * For a text attribute this contains the text content. This is used by most |
469 * attributes and represents the value that will be assigned to them. If this | 499 * attributes and represents the value that will be assigned to them. If this |
470 * has been assigned then [isText] will be true. | 500 * has been assigned then [isText] will be true. |
471 * | 501 * |
472 * The entries in this list correspond to the entries in [bindings], and this | 502 * The entries in this list correspond to the entries in [bindings], and this |
473 * will always have one more item than bindings. For example: | 503 * will always have one more item than bindings. For example: |
474 * | 504 * |
475 * href="t0 {{b1}} t1 {{b2}} t2" | 505 * href="t0 {{b1}} t1 {{b2}} t2" |
476 * | 506 * |
477 * Here textContent would be `["t0 ", " t1 ", " t2"]` and bindings would be | 507 * Here textContent would be `["t0 ", " t1 ", " t2"]` and bindings would be |
478 * `["b1", "b2"]`. | 508 * `["b1", "b2"]`. |
479 */ | 509 */ |
480 final List<String> textContent; | 510 final List<String> textContent; |
481 | 511 |
482 AttributeInfo(this.bindings, {this.isStyle: false, this.isClass: false, | 512 AttributeInfo(this.bindings, {this.isStyle: false, this.isClass: false, |
483 this.textContent}) { | 513 this.textContent, this.customTwoWayBinding: false}) { |
484 | 514 |
485 assert(isText || isClass || bindings.length == 1); | 515 assert(isText || isClass || bindings.length == 1); |
486 assert(bindings.length > 0); | 516 assert(bindings.length > 0); |
487 assert(!isText || textContent.length == bindings.length + 1); | 517 assert(!isText || textContent.length == bindings.length + 1); |
488 assert((isText ? 1 : 0) + (isClass ? 1 : 0) + (isStyle ? 1 : 0) <= 1); | 518 assert((isText ? 1 : 0) + (isClass ? 1 : 0) + (isStyle ? 1 : 0) <= 1); |
489 } | 519 } |
490 | 520 |
491 /** | 521 /** |
492 * A value that will be monitored for changes. All attributes have a single | 522 * A value that will be monitored for changes. All attributes have a single |
493 * bound value unless [isClass] or [isText] is true. | 523 * bound value unless [isClass] or [isText] is true. |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 } | 661 } |
632 | 662 |
633 visitChildren(ElementInfo info) { | 663 visitChildren(ElementInfo info) { |
634 for (var child in info.children) { | 664 for (var child in info.children) { |
635 var result = visit(child); | 665 var result = visit(child); |
636 if (result != null) return result; | 666 if (result != null) return result; |
637 } | 667 } |
638 return null; | 668 return null; |
639 } | 669 } |
640 } | 670 } |
OLD | NEW |