Merge pull request #892 from keertip/inherited
links for inherited elements, reduce file generation
diff --git a/lib/src/html_generator.dart b/lib/src/html_generator.dart
index 53712b7..3adb5eb 100644
--- a/lib/src/html_generator.dart
+++ b/lib/src/html_generator.dart
@@ -224,15 +224,15 @@
generateProperty(package, lib, clazz, property);
});
- clazz.allInstanceProperties.forEach((property) {
+ clazz.propertiesForPages.forEach((property) {
generateProperty(package, lib, clazz, property);
});
- clazz.allInstanceMethods.forEach((method) {
+ clazz.methodsForPages.forEach((method) {
generateMethod(package, lib, clazz, method);
});
- clazz.allOperators.forEach((operator) {
+ clazz.operatorsForPages.forEach((operator) {
generateMethod(package, lib, clazz, operator);
});
diff --git a/lib/src/model.dart b/lib/src/model.dart
index 82b5c06..41d6021 100644
--- a/lib/src/model.dart
+++ b/lib/src/model.dart
@@ -279,40 +279,23 @@
ElementType get modelType => _modelType;
- /// Returns the [ClassElement] that encloses this.
- /// TODO: this is in the wrong place. Not all ModelElements have
- /// an enclosing class.
- /// Why is this here?
- Class get enclosingClass {
- // A class's enclosing element is a library, and there isn't a
- // modelelement for a library.
- if (element.enclosingElement != null &&
- element.enclosingElement is ClassElement) {
- return new ModelElement.from(element.enclosingElement, library) as Class;
- } else {
- return null;
- }
- }
-
Package get package =>
(this is Library) ? (this as Library).package : this.library.package;
String get linkedName {
- if (enclosingClass != null &&
- !package.isDocumented(enclosingClass.element)) {
- return htmlEscape(name);
- } else if (enclosingClass == null && !package.isDocumented(this.element)) {
- return htmlEscape(name);
- }
-
if (name.startsWith('_')) {
return htmlEscape(name);
}
+ if (!(this is Method || this is Field) && !package.isDocumented(element)) {
+ return htmlEscape(name);
+ }
- // this smells like it's in the wrong place
- Class c = enclosingClass;
- if (c != null && c.name.startsWith('_')) {
- return '${c.name}.${htmlEscape(name)}';
+ ModelElement c = (this is EnclosedElement)
+ ? (this as EnclosedElement).enclosingElement
+ : null;
+ if (c != null) {
+ if (!package.isDocumented(c.element)) return htmlEscape(name);
+ if (c.name.startsWith('_')) return '${c.name}.${htmlEscape(name)}';
}
return '<a class="${isDeprecated ? 'deprecated' : ''}" href="${href}">$name</a>';
@@ -422,6 +405,7 @@
class Package implements Nameable, Documentable {
final List<Library> _libraries = [];
final PackageMeta packageMeta;
+ final Map<String, Library> elementLibaryMap = {};
String _docsAsHtml;
String get name => packageMeta.name;
@@ -461,6 +445,7 @@
libraryElements.forEach((element) {
var lib = new Library(element, this);
Library._libraryMap.putIfAbsent(lib.name, () => lib);
+ elementLibaryMap.putIfAbsent('${lib.kind}.${lib.name}', () => lib);
_libraries.add(lib);
});
@@ -489,10 +474,8 @@
if (element.enclosingElement is! CompilationUnitElement) {
el = element.enclosingElement;
} else {
- // in this case, element is an accessor for a library-level variable,
- // likely a const. We, in this case, actually don't want the enclosing
- // element because it's a compilation unit, whatever that is.
- el = element;
+ // get the library
+ el = element.enclosingElement.enclosingElement;
}
} else if (element is TopLevelVariableElement) {
final TopLevelVariableElement variableElement = element;
@@ -506,7 +489,6 @@
} else {
el = element;
}
-
return _libraries.firstWhere((lib) => lib.hasInExportedNamespace(el),
orElse: () => null);
}
@@ -524,12 +506,15 @@
return null;
}
- return libraries.firstWhere((l) => l.hasInExportedNamespace(e), orElse: () {
- // TODO: this is almost certainly a bug: we shouldn't be setting
- // the library's package to this, because e.library could be a core Dart
- // library.
- return new Library(e.library, this);
- });
+ Library lib = elementLibaryMap['${e.kind}.${e.name}'];
+ if (lib != null) return lib;
+ lib = libraries.firstWhere((l) => l.hasInExportedNamespace(e),
+ orElse: () {});
+ if (lib != null) {
+ elementLibaryMap.putIfAbsent('${e.kind}.${e.name}', () => lib);
+ return lib;
+ }
+ return new Library(e.library, this);
}
}
@@ -778,16 +763,19 @@
List<Operator> _operators;
List<Operator> _inheritedOperators;
List<Operator> _allOperators;
+ List<Operator> _genPageOperators = [];
List<Method> _inheritedMethods;
List<Method> _staticMethods;
List<Method> _instanceMethods;
List<Method> _allInstanceMethods;
+ List<Method> _genPageMethods = [];
List<Field> _fields;
List<Field> _staticFields;
List<Field> _constants;
List<Field> _instanceFields;
List<Field> _inheritedProperties;
List<Field> _allInstanceProperties;
+ List<Field> _genPageProperties = [];
ClassElement get _cls => (element as ClassElement);
@@ -922,6 +910,7 @@
.where((f) => !f.isStatic)
.toList(growable: false)..sort(byName);
+ _genPageProperties.addAll(_instanceFields);
return _instanceFields;
}
@@ -968,6 +957,7 @@
_operators = _methods.where((m) => m.isOperator).toList(growable: false)
..sort(byName);
+ _genPageOperators.addAll(_operators);
return _operators;
}
@@ -1002,6 +992,7 @@
.where((m) => !m.isStatic && !m.isOperator)
.toList(growable: false)..sort(byName);
+ _genPageMethods.addAll(_instanceMethods);
return _instanceMethods;
}
@@ -1028,6 +1019,11 @@
List<ExecutableElement> vs = [];
Set<String> uniqueNames = new Set();
+ instanceProperties.forEach((f) {
+ if (f._setter != null) uniqueNames.add(f._setter.name);
+ if (f._getter != null) uniqueNames.add(f._getter.name);
+ });
+
for (var i = 0; i < cmap.size; i++) {
// XXX: if we care about showing a hierarchy with our inherited methods,
// then don't do this
@@ -1053,7 +1049,15 @@
!value.isOperator &&
value.enclosingElement != null &&
value.enclosingElement.name != 'Object') {
- _inheritedMethods.add(new Method.inherited(value, this, this.library));
+ if (!package.isDocumented(value.enclosingElement)) {
+ Method m = new Method.inherited(value, this, library);
+ _inheritedMethods.add(m);
+ _genPageMethods.add(m);
+ } else {
+ Library lib = package._getLibraryFor(value.enclosingElement);
+ _inheritedMethods.add(new Method.inherited(
+ value, new Class(value.enclosingElement, lib), lib));
+ }
}
}
@@ -1110,8 +1114,15 @@
}
for (ExecutableElement value in vs.values) {
- _inheritedOperators
- .add(new Operator.inherited(value, this, this.library));
+ if (!package.isDocumented(value.enclosingElement)) {
+ Operator o = new Operator.inherited(value, this, library);
+ _inheritedOperators.add(o);
+ _genPageOperators.add(o);
+ } else {
+ Library lib = package._getLibraryFor(value.enclosingElement);
+ _inheritedOperators.add(new Operator.inherited(
+ value, new Class(value.enclosingElement, lib), lib));
+ }
}
_inheritedOperators.sort(byName);
@@ -1172,7 +1183,15 @@
if (_inheritedProperties.any((f) => f.element == e)) {
continue;
}
- _inheritedProperties.add(new Field.inherited(e, this, this.library));
+ if (!package.isDocumented(value.enclosingElement)) {
+ Field f = new Field.inherited(e, this, library);
+ _inheritedProperties.add(f);
+ _genPageProperties.add(f);
+ } else {
+ Library lib = package._getLibraryFor(e.enclosingElement);
+ _inheritedProperties.add(
+ new Field.inherited(e, new Class(e.enclosingElement, lib), lib));
+ }
}
}
@@ -1199,6 +1218,12 @@
return _allInstanceProperties;
}
+ List<Field> get propertiesForPages => _genPageProperties;
+
+ List<Method> get methodsForPages => _genPageMethods;
+
+ List<Operator> get operatorsForPages => _genPageOperators;
+
bool get isErrorOrException {
bool _doCheck(InterfaceType type) {
return (type.element.library.isDartCore &&
@@ -1363,15 +1388,11 @@
String get kind => 'property';
@override
- Class get enclosingClass => _enclosingClass;
-
- @override
ModelElement get enclosingElement {
if (_enclosingClass == null) {
- return new ModelElement.from(_field.enclosingElement, library);
- } else {
- return new ModelElement.from(_enclosingClass.element, library);
+ _enclosingClass = new ModelElement.from(_field.enclosingElement, library);
}
+ return _enclosingClass;
}
void _setModelType() {
@@ -1425,9 +1446,9 @@
@override
String get href {
- if (enclosingElement.element is ClassElement) {
+ if (enclosingElement is Class) {
return '${library.dirName}/${enclosingElement.name}/$name.html';
- } else if (enclosingElement.element is LibraryElement) {
+ } else if (enclosingElement is Library) {
return '${library.dirName}/$name.html';
} else {
throw new StateError(
@@ -1498,7 +1519,7 @@
@override
String get name {
String constructorName = element.name;
- Class c = enclosingClass;
+ Class c = new ModelElement.from(element.enclosingElement, library) as Class;
if (constructorName.isEmpty) {
return c.name;
} else {
@@ -1526,18 +1547,15 @@
}
@override
- Class get enclosingClass => _enclosingClass;
-
- @override
String get kind => 'method';
@override
ModelElement get enclosingElement {
if (_enclosingClass == null) {
- return new ModelElement.from(_method.enclosingElement, library);
- } else {
- return new ModelElement.from(_enclosingClass.element, library);
+ _enclosingClass =
+ new ModelElement.from(_method.enclosingElement, library);
}
+ return _enclosingClass;
}
Method get overriddenElement {
@@ -1630,8 +1648,14 @@
String get kind => 'accessor';
@override
- ModelElement get enclosingElement =>
- new ModelElement.from(_accessor.enclosingElement, library);
+ ModelElement get enclosingElement {
+ if (_accessor.enclosingElement is CompilationUnitElement) {
+ return package
+ ._getLibraryFor(_accessor.enclosingElement.enclosingElement);
+ }
+
+ return new ModelElement.from(_accessor.enclosingElement, library);
+ }
bool get isGetter => _accessor.isGetter;
diff --git a/lib/templates/_callable.html b/lib/templates/_callable.html
index 9915860..4df86f6 100644
--- a/lib/templates/_callable.html
+++ b/lib/templates/_callable.html
@@ -1,5 +1,5 @@
<dt id="{{htmlId}}" class="callable">
- <a href="{{href}}">{{>name_summary}}</a><span class="signature">(<wbr>{{{ linkedParamsNoMetadata }}})
+ <span class="name {{#isDeprecated}}deprecated{{/isDeprecated}}">{{{linkedName}}}</span><span class="signature">(<wbr>{{{ linkedParamsNoMetadata }}})
→
<span class="returntype">{{{ linkedReturnType }}}</span>
</span>
diff --git a/test/model_test.dart b/test/model_test.dart
index 503e6aa..442121a 100644
--- a/test/model_test.dart
+++ b/test/model_test.dart
@@ -788,23 +788,27 @@
.singleWhere((m) => m.name == 'convertToMap');
});
- test('an inherited method has the inheriting class as the enclosing class',
+ test(
+ 'an inherited method has class as the enclosing class, when superclass not in package',
() {
expect(inheritedClear.enclosingElement.name, equals('CatString'));
- expect(inheritedClear.enclosingClass.name, equals('CatString'));
});
- test('inherited method has the inheriting class library', () {
+ test(
+ 'inherited method has the current library, when superclass library not in package',
+ () {
expect(inheritedClear.library.name, equals('ex'));
});
test(
- 'an inherited method from the core SDK has a href local to the inheriting class',
+ 'an inherited method from the core SDK has a href relative to the package class',
() {
expect(inheritedClear.href, equals('ex/CatString/clear.html'));
});
- test('an inherited method has a linkedName that includes an HTML link', () {
+ test(
+ 'an inherited method has linked to enclosed class name when superclass not in package',
+ () {
expect(inheritedClear.linkedName,
equals('<a class="" href="ex/CatString/clear.html">clear</a>'));
});
@@ -866,20 +870,20 @@
expect(plus.isInherited, isTrue);
});
- test('if inherited, has the inheriting class', () {
- expect(plus.enclosingClass.name, equals('SpecializedDuration'));
+ test('if inherited, and superclass not in package', () {
expect(plus.enclosingElement.name, equals('SpecializedDuration'));
});
- test("if inherited, has the inheriting class's library", () {
- expect(plus.library, equals(specializedDuration.library));
+ test("if inherited, has the class's library", () {
+ expect(plus.library.name, 'ex');
});
- test('if inherited, has a href relative to inheriting class', () {
+ test('if inherited, has a href relative to enclosed class', () {
expect(plus.href, equals('ex/SpecializedDuration/operator_plus.html'));
});
- test('if inherited, has a linkedName', () {
+ test('if inherited and superclass not in package, link to enclosed class',
+ () {
expect(
plus.linkedName,
equals(
@@ -891,7 +895,8 @@
Class c, LongFirstLine, CatString;
Field f1, f2, constField, dynamicGetter, onlySetter;
Field lengthX;
- Field sFromApple;
+ Field sFromApple, mInB;
+ ;
Field isEmpty;
setUp(() {
@@ -918,20 +923,29 @@
.firstWhere((c) => c.name == 'Apple')
.allInstanceProperties
.firstWhere((p) => p.name == 's');
+ mInB = exLibrary.allClasses
+ .firstWhere((c) => c.name == 'B')
+ .allInstanceProperties
+ .firstWhere((p) => p.name == 'm');
});
- test('inherited property has a linked name', () {
+ test('inherited property has a linked name to superclass in package', () {
+ expect(
+ mInB.linkedName, equals('<a class="" href="ex/Apple/m.html">m</a>'));
+ });
+
+ test(
+ 'inherited property has linked name to enclosed class, if superclass is not in package',
+ () {
expect(isEmpty.linkedName,
equals('<a class="" href="ex/CatString/isEmpty.html">isEmpty</a>'));
});
- test('inherited property has the inheriting class as the enclosing class',
- () {
- expect(isEmpty.enclosingClass.name, equals('CatString'));
+ test('inherited property has the enclosing class', () {
expect(isEmpty.enclosingElement.name, equals('CatString'));
});
- test('inherited property has the inheriting class library', () {
+ test('inherited property has the enclosing class library', () {
expect(isEmpty.library.name, equals('ex'));
});