Skip to content

Implement new-style mixin support for Dart 2.1 #1765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Oct 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ os:
- osx
- linux


install:
- ./tool/install_travis.sh

Expand Down
4 changes: 3 additions & 1 deletion lib/src/dartdoc_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,9 @@ abstract class DartdocOption<T> {
} else if (valueWithContext.value is Map<String, String>) {
resolvedPaths = valueWithContext.resolvedValue.values.toList();
} else {
assert(false, "Trying to ensure existence of unsupported type "
assert(
false,
"Trying to ensure existence of unsupported type "
"${valueWithContext.value.runtimeType}");
}
for (String path in resolvedPaths) {
Expand Down
45 changes: 45 additions & 0 deletions lib/src/html/html_generator_instance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,44 @@ class HtmlGeneratorInstance {
}
}

for (var mixin in filterNonDocumented(lib.mixins)) {
generateMixins(_packageGraph, lib, mixin);
for (var constructor in filterNonDocumented(mixin.constructors)) {
if (!constructor.isCanonical) continue;
generateConstructor(_packageGraph, lib, mixin, constructor);
}

for (var constant in filterNonDocumented(mixin.constants)) {
if (!constant.isCanonical) continue;
generateConstant(_packageGraph, lib, mixin, constant);
}

for (var property in filterNonDocumented(mixin.staticProperties)) {
if (!property.isCanonical) continue;
generateProperty(_packageGraph, lib, mixin, property);
}

for (var property in filterNonDocumented(mixin.propertiesForPages)) {
if (!property.isCanonical) continue;
generateProperty(_packageGraph, lib, mixin, property);
}

for (var method in filterNonDocumented(mixin.methodsForPages)) {
if (!method.isCanonical) continue;
generateMethod(_packageGraph, lib, mixin, method);
}

for (var operator in filterNonDocumented(mixin.operatorsForPages)) {
if (!operator.isCanonical) continue;
generateMethod(_packageGraph, lib, mixin, operator);
}

for (var method in filterNonDocumented(mixin.staticMethods)) {
if (!method.isCanonical) continue;
generateMethod(_packageGraph, lib, mixin, method);
}
}

for (var eNum in filterNonDocumented(lib.enums)) {
generateEnum(_packageGraph, lib, eNum);
for (var property in filterNonDocumented(eNum.propertiesForPages)) {
Expand Down Expand Up @@ -239,6 +277,13 @@ class HtmlGeneratorInstance {
pathLib.joinAll(clazz.href.split('/')), _templates.classTemplate, data);
}

void generateMixins(PackageGraph packageGraph, Library lib, Mixin mixin) {
TemplateData data =
new MixinTemplateData(_options, packageGraph, lib, mixin);
_build(
pathLib.joinAll(mixin.href.split('/')), _templates.mixinTemplate, data);
}

void generateConstructor(PackageGraph packageGraph, Library lib, Class clazz,
Constructor constructor) {
TemplateData data = new ConstructorTemplateData(
Expand Down
38 changes: 19 additions & 19 deletions lib/src/html/template_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,20 @@ class LibraryTemplateData extends TemplateData<Library> {
Library get self => library;
}

class ClassTemplateData extends TemplateData<Class> {
/// Template data for Dart 2.1-style mixin declarations.
class MixinTemplateData extends ClassTemplateData<Mixin> {
final Mixin mixin;

MixinTemplateData(HtmlOptions htmlOptions, PackageGraph packageGraph,
Library library, this.mixin)
: super(htmlOptions, packageGraph, library, mixin);

@override
Mixin get self => mixin;
}

/// Base template data class for [Class], [Enum], and [Mixin].
class ClassTemplateData<T extends Class> extends TemplateData<T> {
final Class clazz;
final Library library;
Class _objectType;
Expand All @@ -219,7 +232,7 @@ class ClassTemplateData extends TemplateData<Class> {
: super(htmlOptions, packageGraph);

@override
Class get self => clazz;
T get self => clazz;
String get linkedObjectType =>
objectType == null ? 'Object' : objectType.linkedName;
@override
Expand Down Expand Up @@ -303,28 +316,15 @@ class ConstructorTemplateData extends TemplateData<Constructor> {
'for the Dart programming language.';
}

class EnumTemplateData extends TemplateData<Enum> {
class EnumTemplateData extends ClassTemplateData<Enum> {
EnumTemplateData(HtmlOptions htmlOptions, PackageGraph packageGraph,
this.library, this.eNum)
: super(htmlOptions, packageGraph);
Library library, Enum eNum)
: super(htmlOptions, packageGraph, library, eNum);

final Library library;
final Enum eNum;
Enum get eNum => clazz;
@override
Enum get self => eNum;
@override
String get layoutTitle => _layoutTitle(eNum.name, 'enum', eNum.isDeprecated);
@override
String get title => '${self.name} enum - ${library.name} library - Dart API';
@override
String get metaDescription =>
'API docs for the ${eNum.name} enum from the ${library.name} library, '
'for the Dart programming language.';
@override
List get navLinks => [packageGraph.defaultPackage, library];
@override
String get htmlBase => '..';
@override
Iterable<Subnav> getSubNavItems() => [
new Subnav('Constants', '${eNum.href}#constants'),
new Subnav('Properties', '${eNum.href}#instance-properties'),
Expand Down
9 changes: 7 additions & 2 deletions lib/src/html/templates.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const _partials = const <String>[
'footer',
'head',
'library',
'mixin',
'packages',
'property',
'features',
Expand Down Expand Up @@ -91,6 +92,7 @@ class Templates {
final TemplateRenderer indexTemplate;
final TemplateRenderer libraryTemplate;
final TemplateRenderer methodTemplate;
final TemplateRenderer mixinTemplate;
final TemplateRenderer propertyTemplate;
final TemplateRenderer topLevelConstantTemplate;
final TemplateRenderer topLevelPropertyTemplate;
Expand Down Expand Up @@ -132,6 +134,7 @@ class Templates {
var topLevelPropertyTemplate =
await _loadTemplate('top_level_property.html');
var typeDefTemplate = await _loadTemplate('typedef.html');
var mixinTemplate = await _loadTemplate('mixin.html');

return new Templates._(
indexTemplate,
Expand All @@ -147,7 +150,8 @@ class Templates {
constantTemplate,
topLevelConstantTemplate,
topLevelPropertyTemplate,
typeDefTemplate);
typeDefTemplate,
mixinTemplate);
}

Templates._(
Expand All @@ -164,5 +168,6 @@ class Templates {
this.constantTemplate,
this.topLevelConstantTemplate,
this.topLevelPropertyTemplate,
this.typeDefTemplate);
this.typeDefTemplate,
this.mixinTemplate);
}
100 changes: 21 additions & 79 deletions lib/src/markdown_processor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -185,66 +185,9 @@ ModelElement _getPreferredClass(ModelElement modelElement) {
return null;
}

// TODO: this is in the wrong place
NodeList<CommentReference> _getCommentRefs(Documentable documentable) {
// Documentable items that aren't related to analyzer elements have no
// CommentReference list.
if (documentable is! ModelElement) return null;
ModelElement modelElement = documentable;

if (modelElement.element.documentationComment == null &&
modelElement.canOverride()) {
var node = modelElement.overriddenElement?.element?.computeNode();
if (node is AnnotatedNode) {
if (node.documentationComment != null) {
return node.documentationComment.references;
}
}
}

if (modelElement.element.computeNode() is AnnotatedNode) {
final AnnotatedNode annotatedNode = modelElement.element.computeNode();
if (annotatedNode.documentationComment != null) {
return annotatedNode.documentationComment.references;
}
} else if (modelElement.element is LibraryElement) {
// handle anonymous libraries
if (modelElement.element.computeNode() == null ||
modelElement.element.computeNode().parent == null) {
return null;
}
var node = modelElement.element.computeNode().parent.parent;
if (node is AnnotatedNode) {
if (node.documentationComment != null) {
return node.documentationComment.references;
}
}
}

// Our references might come from somewhere up in the inheritance chain.
// TODO(jcollins-g): rationalize this and all other places where docs are
// inherited to be consistent.
if (modelElement.element is ClassMemberElement) {
var node = modelElement.element
.getAncestor((e) => e is ClassElement)
.computeNode();
if (node is AnnotatedNode) {
if (node.documentationComment != null) {
return node.documentationComment.references;
}
}
}
return null;
}

/// Returns null if element is a parameter.
MatchingLinkResult _getMatchingLinkElement(
String codeRef, Warnable element, List<CommentReference> commentRefs) {
// By debugging inspection, it seems correct to not warn when we don't have
// CommentReferences; there's actually nothing that needs resolving in
// that case.
if (commentRefs == null) return new MatchingLinkResult(null, warn: false);

if (!codeRef.contains(isConstructor) &&
codeRef.contains(notARealDocReference)) {
// Don't waste our time on things we won't ever find.
Expand All @@ -254,7 +197,7 @@ MatchingLinkResult _getMatchingLinkElement(
ModelElement refModelElement;

// Try expensive not-scoped lookup.
if (refModelElement == null) {
if (refModelElement == null && element is ModelElement) {
Class preferredClass = _getPreferredClass(element);
refModelElement =
_findRefElementInLibrary(codeRef, element, commentRefs, preferredClass);
Expand Down Expand Up @@ -318,22 +261,25 @@ MatchingLinkResult _getMatchingLinkElement(
/// Given a set of commentRefs, return the one whose name matches the codeRef.
Element _getRefElementFromCommentRefs(
List<CommentReference> commentRefs, String codeRef) {
for (CommentReference ref in commentRefs) {
if (ref.identifier.name == codeRef) {
bool isConstrElement = ref.identifier.staticElement is ConstructorElement;
// Constructors are now handled by library search.
if (!isConstrElement) {
Element refElement = ref.identifier.staticElement;
if (refElement is PropertyAccessorElement) {
// yay we found an accessor that wraps a const, but we really
// want the top-level field itself
refElement = (refElement as PropertyAccessorElement).variable;
}
if (refElement is PrefixElement) {
// We found a prefix element, but what we really want is the library element.
refElement = (refElement as PrefixElement).enclosingElement;
if (commentRefs != null) {
for (CommentReference ref in commentRefs) {
if (ref.identifier.name == codeRef) {
bool isConstrElement =
ref.identifier.staticElement is ConstructorElement;
// Constructors are now handled by library search.
if (!isConstrElement) {
Element refElement = ref.identifier.staticElement;
if (refElement is PropertyAccessorElement) {
// yay we found an accessor that wraps a const, but we really
// want the top-level field itself
refElement = (refElement as PropertyAccessorElement).variable;
}
if (refElement is PrefixElement) {
// We found a prefix element, but what we really want is the library element.
refElement = (refElement as PrefixElement).enclosingElement;
}
return refElement;
}
return refElement;
}
}
}
Expand Down Expand Up @@ -719,7 +665,7 @@ void _getResultsForClass(Class tryClass, String codeRefChomped,
}

String _linkDocReference(
String codeRef, Warnable warnable, NodeList<CommentReference> commentRefs) {
String codeRef, Warnable warnable, List<CommentReference> commentRefs) {
MatchingLinkResult result;
result = _getMatchingLinkElement(codeRef, warnable, commentRefs);
final ModelElement linkedElement = result.element;
Expand Down Expand Up @@ -942,11 +888,7 @@ class Documentation {
return _asOneLiner;
}

NodeList<CommentReference> _commentRefs;
NodeList<CommentReference> get commentRefs {
if (_commentRefs == null) _commentRefs = _getCommentRefs(_element);
return _commentRefs;
}
List<CommentReference> get commentRefs => _element.commentRefs;

void _renderHtmlForDartdoc(bool processAllDocs) {
Tuple3<String, String, bool> renderResults =
Expand Down
Loading