| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library category_item; | 5 library category_item; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 | 9 |
| 10 import 'package:dartdoc_viewer/data.dart'; | 10 import 'package:dartdoc_viewer/data.dart'; |
| 11 import 'package:dartdoc_viewer/read_yaml.dart'; | 11 import 'package:dartdoc_viewer/read_yaml.dart'; |
| 12 import 'package:polymer/polymer.dart'; | 12 import 'package:polymer/polymer.dart'; |
| 13 import 'package:yaml/yaml.dart'; | 13 import 'package:yaml/yaml.dart'; |
| 14 import 'package:dartdoc_viewer/location.dart'; | 14 import 'package:dartdoc_viewer/location.dart'; |
| 15 import 'package:dartdoc_viewer/search.dart' show searchIndex; | 15 import 'package:dartdoc_viewer/search.dart' show searchIndex; |
| 16 import 'package:collection/equality.dart'; | 16 import 'package:collection/equality.dart'; |
| 17 | 17 |
| 18 // TODO(tmandel): Don't hardcode in a path if it can be avoided. | 18 // TODO(tmandel): Don't hardcode in a path if it can be avoided. |
| 19 @reflectable const docsPath = 'docs/'; | 19 @reflectable const docsPath = 'docs/'; |
| 20 | 20 |
| 21 nothing() => null; | 21 _returnNull() => null; |
| 22 | 22 |
| 23 /** | 23 /** |
| 24 * Abstract class for anything that holds values and can be displayed. | 24 * Abstract class for anything that holds values and can be displayed. |
| 25 */ | 25 */ |
| 26 @reflectable class Container extends Observable { | 26 @reflectable class Container extends Observable { |
| 27 final String name; | 27 final String name; |
| 28 @observable String comment = '<span></span>'; | 28 @observable String comment = '<span></span>'; |
| 29 bool get hasComment => !hasNoComment; | 29 bool get hasComment => !hasNoComment; |
| 30 bool get hasNoComment => | 30 bool get hasNoComment => |
| 31 comment == '<span></span>' || comment == '<div></div>'; | 31 comment == '<span></span>' || comment == '<div></div>'; |
| 32 | 32 |
| 33 Container(this.name, [this.comment]); | 33 Container(this.name, [this.comment]); |
| 34 | 34 |
| 35 String toString() => "$runtimeType($name)"; | 35 String toString() => "$runtimeType($name)"; |
| 36 } | 36 } |
| 37 | 37 |
| 38 /** Wraps a comment in span element to make it a single HTML Element. */ | 38 /** Wraps a comment in span element to make it a single HTML Element. */ |
| 39 String _wrapComment(String comment) => | 39 String _wrapComment(String comment) => |
| 40 comment == null ? '<div></div>' : '<div>$comment</div>'; | 40 comment == null ? '<div></div>' : '<div>$comment</div>'; |
| 41 | 41 |
| 42 /** | 42 /** |
| 43 * A [Container] that contains other [Container]s to be displayed. | 43 * A [Container] that contains other [Container]s to be displayed. |
| 44 */ | 44 */ |
| 45 @reflectable class Category extends Container { | 45 @reflectable class Category extends Container { |
| 46 List<Container> content = []; | 46 List<Container> content = []; |
| 47 Set<String> memberNames = new Set<String>(); | 47 Set<String> memberNames = new Set<String>(); |
| 48 int inheritedCounter = 0; | 48 int inheritedCounter = 0; |
| 49 int memberCounter = 0; | 49 int memberCounter = 0; |
| 50 | 50 |
| 51 Item memberNamed(String name, {orElse : nothing}) => | 51 Item memberNamed(String name, {orElse : _returnNull}) => |
| 52 content.firstWhere((x) => x.name == name, orElse: orElse); | 52 content.firstWhere((x) => x.name == name, orElse: orElse); |
| 53 | 53 |
| 54 Category.forClasses(List<Map> classes, String name, | 54 Category.forClasses(List<Map> classes, String name, |
| 55 {bool isAbstract: false}) : super(name) { | 55 {bool isAbstract: false}) : super(name) { |
| 56 if (classes != null) { | 56 if (classes != null) { |
| 57 classes.forEach((clazz) => | 57 classes.forEach((clazz) => |
| 58 content.add(new Class.forPlaceholder(clazz['qualifiedName'], | 58 content.add(new Class.forPlaceholder(clazz['qualifiedName'], |
| 59 clazz['preview']))); | 59 clazz['preview']))); |
| 60 } | 60 } |
| 61 } | 61 } |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 /// For non-inherited items, this will just be the [location]. | 232 /// For non-inherited items, this will just be the [location]. |
| 233 DocsLocation get localLocation => location; | 233 DocsLocation get localLocation => location; |
| 234 | 234 |
| 235 String get anchorHref => Uri.encodeFull(anchorHrefLocation.withAnchor); | 235 String get anchorHref => Uri.encodeFull(anchorHrefLocation.withAnchor); |
| 236 | 236 |
| 237 /// [anchorHref] but with the leading # separator. | 237 /// [anchorHref] but with the leading # separator. |
| 238 String get prefixedAnchorHref => locationPrefixed(anchorHref); | 238 String get prefixedAnchorHref => locationPrefixed(anchorHref); |
| 239 | 239 |
| 240 bool get isLoaded => true; | 240 bool get isLoaded => true; |
| 241 | 241 |
| 242 Item memberNamed(String name, {Function orElse : nothing}) => nothing(); | 242 Item memberNamed(String name, {Function orElse : _returnNull}) => _returnNull(
); |
| 243 | 243 |
| 244 Item get owner => _owner == null ? | 244 Item get owner => _owner == null ? |
| 245 _owner = pageIndex[location.parentQualifiedName] : _owner; | 245 _owner = pageIndex[location.parentQualifiedName] : _owner; |
| 246 | 246 |
| 247 /// Return true if [possibleOwner] is anywhere in our chain of owners. | 247 /// Return true if [possibleOwner] is anywhere in our chain of owners. |
| 248 bool isOwnedBy(Item possibleOwner) { | 248 bool isOwnedBy(Item possibleOwner) { |
| 249 if (owner == null || possibleOwner == null) return false; | 249 if (owner == null || possibleOwner == null) return false; |
| 250 if (owner == possibleOwner) return true; | 250 if (owner == possibleOwner) return true; |
| 251 return owner.isOwnedBy(possibleOwner); | 251 return owner.isOwnedBy(possibleOwner); |
| 252 } | 252 } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 libraries..remove(mainLib)..insert(0, mainLib); | 347 libraries..remove(mainLib)..insert(0, mainLib); |
| 348 var libs = yaml['libraries']; | 348 var libs = yaml['libraries']; |
| 349 var main = libs.firstWhere((each) => each['name'] == mainLib.name); | 349 var main = libs.firstWhere((each) => each['name'] == mainLib.name); |
| 350 var intro = main['packageIntro']; | 350 var intro = main['packageIntro']; |
| 351 if (intro != null && !intro.isEmpty) { | 351 if (intro != null && !intro.isEmpty) { |
| 352 comment = _wrapComment(intro); | 352 comment = _wrapComment(intro); |
| 353 } | 353 } |
| 354 } | 354 } |
| 355 } | 355 } |
| 356 | 356 |
| 357 Item memberNamed(String name, {Function orElse : nothing}) { | 357 Item memberNamed(String name, {Function orElse : _returnNull}) { |
| 358 return libraries.firstWhere( | 358 return libraries.firstWhere( |
| 359 (each) => each.name == name || each.decoratedName == name, | 359 (each) => each.name == name || each.decoratedName == name, |
| 360 orElse: orElse); | 360 orElse: orElse); |
| 361 } | 361 } |
| 362 } | 362 } |
| 363 | 363 |
| 364 /// Runs through the member structure and creates path information. | 364 /// Runs through the member structure and creates path information. |
| 365 @reflectable void buildHierarchy(Item page, Item previous) { | 365 @reflectable void buildHierarchy(Item page, Item previous) { |
| 366 if (page.path.isEmpty) { | 366 if (page.path.isEmpty) { |
| 367 page.path | 367 page.path |
| 368 ..addAll(previous.path) | 368 ..addAll(previous.path) |
| 369 ..add(page); | 369 ..add(page); |
| 370 } | 370 } |
| 371 page.addToHierarchy(); | 371 page.addToHierarchy(); |
| 372 } | 372 } |
| 373 | 373 |
| 374 /** | 374 /** |
| 375 * An [Item] that is lazily loaded. | 375 * An [Item] that is lazily loaded. |
| 376 */ | 376 */ |
| 377 @reflectable abstract class LazyItem extends Item { | 377 @reflectable abstract class LazyItem extends Item { |
| 378 bool isLoaded = false; | 378 bool isLoaded = false; |
| 379 String previewComment; | 379 final String previewComment; |
| 380 | 380 |
| 381 LazyItem(String qualifiedName, String name, previewComment, | 381 LazyItem(String qualifiedName, String name, this.previewComment, |
| 382 [String comment]) : previewComment = previewComment , | 382 [String comment]) |
| 383 super(name, qualifiedName, comment); | 383 : super(name, qualifiedName, comment); |
| 384 | 384 |
| 385 /// Loads this [Item]'s data and populates all fields. | 385 /// Loads this [Item]'s data and populates all fields. |
| 386 Future load() { | 386 Future load() { |
| 387 if (isLoaded) return new Future.value(this); | 387 if (isLoaded) return new Future.value(this); |
| 388 var location = '$docsPath$qualifiedName.' + (isYaml ? 'yaml' : 'json'); | 388 var location = '$docsPath$qualifiedName.' + (isYaml ? 'yaml' : 'json'); |
| 389 var data = retrieveFileContents(location); | 389 var data = retrieveFileContents(location); |
| 390 return data.then((response) { | 390 return data.then((response) { |
| 391 var yaml = isYaml ? loadYaml(response) : JSON.decode(response); | 391 var yaml = isYaml ? loadYaml(response) : JSON.decode(response); |
| 392 loadValues(yaml); | 392 loadValues(yaml); |
| 393 buildHierarchy(this, this); | 393 buildHierarchy(this, this); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 } | 461 } |
| 462 | 462 |
| 463 String get decoratedName { | 463 String get decoratedName { |
| 464 return isDartLibrary ? | 464 return isDartLibrary ? |
| 465 name.replaceAll('-dom-', '-').replaceAll('-', ':') : | 465 name.replaceAll('-dom-', '-').replaceAll('-', ':') : |
| 466 name.replaceAll('-', '.'); | 466 name.replaceAll('-', '.'); |
| 467 } | 467 } |
| 468 | 468 |
| 469 bool get isDartLibrary => home != null && home.isTopLevelHome; | 469 bool get isDartLibrary => home != null && home.isTopLevelHome; |
| 470 | 470 |
| 471 Item memberNamed(String name, {Function orElse : nothing}) { | 471 Item memberNamed(String name, {Function orElse : _returnNull}) { |
| 472 if (name == null || !isLoaded) return orElse(); | 472 if (name == null || !isLoaded) return orElse(); |
| 473 for (var category in | 473 for (var category in |
| 474 [classes, functions, variables, operators, typedefs, errors]) { | 474 [classes, functions, variables, operators, typedefs, errors]) { |
| 475 var member = category.memberNamed(name, orElse: nothing); | 475 var member = category.memberNamed(name, orElse: _returnNull); |
| 476 if (member != null) return member; | 476 if (member != null) return member; |
| 477 } | 477 } |
| 478 return orElse(); | 478 return orElse(); |
| 479 } | 479 } |
| 480 } | 480 } |
| 481 | 481 |
| 482 /** | 482 /** |
| 483 * An [Item] that describes a single Dart class. | 483 * An [Item] that describes a single Dart class. |
| 484 */ | 484 */ |
| 485 @reflectable class Class extends LazyItem { | 485 @reflectable class Class extends LazyItem { |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 var out = new StringBuffer(); | 645 var out = new StringBuffer(); |
| 646 out.write(name); | 646 out.write(name); |
| 647 if (generics.isNotEmpty) { | 647 if (generics.isNotEmpty) { |
| 648 // Use a non-breaking space character, not because this will | 648 // Use a non-breaking space character, not because this will |
| 649 // get escaped. | 649 // get escaped. |
| 650 out.writeAll(["<", generics.join(",\u{00A0}"), ">"]); | 650 out.writeAll(["<", generics.join(",\u{00A0}"), ">"]); |
| 651 } | 651 } |
| 652 return out.toString(); | 652 return out.toString(); |
| 653 } | 653 } |
| 654 | 654 |
| 655 Item memberNamed(String name, {Function orElse : nothing}) { | 655 Item memberNamed(String name, {Function orElse : _returnNull}) { |
| 656 if (name == null) return orElse(); | 656 if (name == null) return orElse(); |
| 657 for (var category in | 657 for (var category in |
| 658 [annotations, constructs, functions, operators, variables]) { | 658 [annotations, constructs, functions, operators, variables]) { |
| 659 var member = category == null ? null : | 659 var member = category == null ? null : |
| 660 category.memberNamed(name, orElse: nothing); | 660 category.memberNamed(name, orElse: _returnNull); |
| 661 if (member != null) return member; | 661 if (member != null) return member; |
| 662 } | 662 } |
| 663 return orElse(); | 663 return orElse(); |
| 664 } | 664 } |
| 665 | 665 |
| 666 } | 666 } |
| 667 | 667 |
| 668 /** | 668 /** |
| 669 * A collection of [Annotation]s. | 669 * A collection of [Annotation]s. |
| 670 */ | 670 */ |
| 671 @reflectable class AnnotationGroup { | 671 @reflectable class AnnotationGroup { |
| 672 List<String> supportedBrowsers = []; | 672 List<String> supportedBrowsers = []; |
| 673 List<Annotation> annotations = []; | 673 List<Annotation> annotations = []; |
| 674 String domName; | 674 String domName; |
| 675 | 675 |
| 676 Item memberNamed(String name, {Function orElse : nothing}) => | 676 Item memberNamed(String name, {Function orElse : _returnNull}) => |
| 677 annotations.firstWhere((a) => a.qualifiedName == name, orElse: orElse); | 677 annotations.firstWhere((a) => a.qualifiedName == name, orElse: orElse); |
| 678 | 678 |
| 679 AnnotationGroup(List annotes) { | 679 AnnotationGroup(List annotes) { |
| 680 var set = new Set(); | 680 var set = new Set(); |
| 681 if (annotes != null) { | 681 if (annotes != null) { |
| 682 annotes.forEach((annotation) { | 682 annotes.forEach((annotation) { |
| 683 if (annotation['name'].endsWith('.SupportedBrowser')) { | 683 if (annotation['name'].endsWith('.SupportedBrowser')) { |
| 684 supportedBrowsers.add(annotation['parameters'].toList().join(' ')); | 684 supportedBrowsers.add(annotation['parameters'].toList().join(' ')); |
| 685 } else if (annotation['name'].endsWith('.DomName')) { | 685 } else if (annotation['name'].endsWith('.DomName')) { |
| 686 domName = annotation['parameters'].first; | 686 domName = annotation['parameters'].first; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 parameters.forEach((name, data) { | 736 parameters.forEach((name, data) { |
| 737 values.add(new Parameter(name, data, this)); | 737 values.add(new Parameter(name, data, this)); |
| 738 }); | 738 }); |
| 739 } | 739 } |
| 740 return values; | 740 return values; |
| 741 } | 741 } |
| 742 | 742 |
| 743 Parameter parameterNamed(String name) => | 743 Parameter parameterNamed(String name) => |
| 744 parameters.firstWhere((x) => x.name == name, orElse: () => null); | 744 parameters.firstWhere((x) => x.name == name, orElse: () => null); |
| 745 | 745 |
| 746 Item memberNamed(String name, {Function orElse : nothing}) { | 746 Item memberNamed(String name, {Function orElse : _returnNull}) { |
| 747 var result = parameterNamed(name); | 747 var result = parameterNamed(name); |
| 748 return result == null ? orElse() : result; | 748 return result == null ? orElse() : result; |
| 749 } | 749 } |
| 750 } | 750 } |
| 751 | 751 |
| 752 /** | 752 /** |
| 753 * An [Item] that describes a single Dart typedef. | 753 * An [Item] that describes a single Dart typedef. |
| 754 */ | 754 */ |
| 755 @reflectable class Typedef extends Parameterized { | 755 @reflectable class Typedef extends Parameterized { |
| 756 LinkableType type; | 756 final LinkableType type; |
| 757 AnnotationGroup annotations; | 757 final AnnotationGroup annotations; |
| 758 final String previewComment; |
| 758 | 759 |
| 759 Typedef(Map yaml) : super(yaml['name'], yaml['qualifiedName'], | 760 Typedef(Map yaml) |
| 760 _wrapComment(yaml['comment'])) { | 761 : type = new LinkableType(yaml['return']), |
| 761 type = new LinkableType(yaml['return']); | 762 annotations = new AnnotationGroup(yaml['annotations']), |
| 763 previewComment = yaml['preview'], |
| 764 super(yaml['name'], yaml['qualifiedName'], |
| 765 _wrapComment(yaml['comment'])) { |
| 762 parameters = getParameters(yaml['parameters']); | 766 parameters = getParameters(yaml['parameters']); |
| 763 annotations = new AnnotationGroup(yaml['annotations']); | |
| 764 } | 767 } |
| 765 } | 768 } |
| 766 | 769 |
| 767 /** | 770 /** |
| 768 * An [Item] that describes a single Dart method. | 771 * An [Item] that describes a single Dart method. |
| 769 */ | 772 */ |
| 770 @reflectable class Method extends Parameterized { | 773 @reflectable class Method extends Parameterized { |
| 771 bool isStatic; | 774 bool isStatic; |
| 772 bool isAbstract; | 775 bool isAbstract; |
| 773 bool isConstant; | 776 bool isConstant; |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 } | 1012 } |
| 1010 | 1013 |
| 1011 | 1014 |
| 1012 bool _boolFor(String key, Map input) { | 1015 bool _boolFor(String key, Map input) { |
| 1013 var value = input[key]; | 1016 var value = input[key]; |
| 1014 if (value == true || value == 'true') return true; | 1017 if (value == true || value == 'true') return true; |
| 1015 if (value == null || value == false || value == 'false') return false; | 1018 if (value == null || value == false || value == 'false') return false; |
| 1016 throw new FormatException("Invalid format, expected boolean key: $key" | 1019 throw new FormatException("Invalid format, expected boolean key: $key" |
| 1017 " value: $value"); | 1020 " value: $value"); |
| 1018 } | 1021 } |
| OLD | NEW |