From c476d64d97ec0bb0858bb9dab5fcfae749588287 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Thu, 30 Sep 2021 11:05:07 -0700 Subject: [PATCH 1/6] Refactor more documentation comment generation into DocumentationComment (#2817) * Straight move * Partial * delete experiment * rebuild * remove ??= from a cut and paste --- .../templates.runtime_renderers.dart | 48 +++-- lib/src/model/documentation_comment.dart | 156 ++++++++++++++- lib/src/model/model_element.dart | 178 ++---------------- lib/src/model/package_graph.dart | 3 +- 4 files changed, 195 insertions(+), 190 deletions(-) diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index f7fa4d9ad4..5abfcd2d64 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -3928,6 +3928,26 @@ class _Renderer_DocumentationComment parent: r); }, ), + 'documentationLocal': Property( + getValue: (CT_ c) => c.documentationLocal, + renderVariable: + (CT_ c, Property self, List remainingNames) { + if (remainingNames.isEmpty) { + return self.getValue(c).toString(); + } + var name = remainingNames.first; + var nextProperty = + _Renderer_String.propertyMap().getValue(name); + return nextProperty.renderVariable(self.getValue(c), + nextProperty, [...remainingNames.skip(1)]); + }, + isNullValue: (CT_ c) => c.documentationLocal == null, + renderValue: (CT_ c, RendererBase r, + List ast, StringSink sink) { + _render_String(c.documentationLocal, ast, r.template, sink, + parent: r); + }, + ), 'fullyQualifiedNameWithoutLibrary': Property( getValue: (CT_ c) => c.fullyQualifiedNameWithoutLibrary, renderVariable: @@ -3971,6 +3991,13 @@ class _Renderer_DocumentationComment getters: _invisibleGetters['ModelElementRenderer']); }, ), + 'needsPrecache': Property( + getValue: (CT_ c) => c.needsPrecache, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.needsPrecache == true, + ), 'pathContext': Property( getValue: (CT_ c) => c.pathContext, renderVariable: (CT_ c, Property self, @@ -4229,6 +4256,7 @@ class _Renderer_Enum extends RendererBase { CT_, () => { ..._Renderer_InheritingContainer.propertyMap(), + ..._Renderer_TypeImplementing.propertyMap(), 'inheritanceChain': Property( getValue: (CT_ c) => c.inheritanceChain, renderVariable: (CT_ c, Property self, @@ -9481,26 +9509,6 @@ class _Renderer_ModelElement extends RendererBase { parent: r)); }, ), - 'documentationLocal': Property( - getValue: (CT_ c) => c.documentationLocal, - renderVariable: - (CT_ c, Property self, List remainingNames) { - if (remainingNames.isEmpty) { - return self.getValue(c).toString(); - } - var name = remainingNames.first; - var nextProperty = - _Renderer_String.propertyMap().getValue(name); - return nextProperty.renderVariable(self.getValue(c), - nextProperty, [...remainingNames.skip(1)]); - }, - isNullValue: (CT_ c) => c.documentationLocal == null, - renderValue: (CT_ c, RendererBase r, - List ast, StringSink sink) { - _render_String(c.documentationLocal, ast, r.template, sink, - parent: r); - }, - ), 'element': Property( getValue: (CT_ c) => c.element, renderVariable: (CT_ c, Property self, diff --git a/lib/src/model/documentation_comment.dart b/lib/src/model/documentation_comment.dart index 1422cc8f5b..405804dc3f 100644 --- a/lib/src/model/documentation_comment.dart +++ b/lib/src/model/documentation_comment.dart @@ -1,6 +1,8 @@ import 'package:args/args.dart'; import 'package:crypto/crypto.dart' as crypto; -import 'package:dartdoc/src/model/model.dart'; +import 'package:dartdoc/src/model/documentable.dart'; +import 'package:dartdoc/src/model/locatable.dart'; +import 'package:dartdoc/src/model/source_code_mixin.dart'; import 'package:dartdoc/src/render/model_element_renderer.dart'; import 'package:dartdoc/src/utils.dart'; import 'package:dartdoc/src/warnings.dart'; @@ -23,9 +25,15 @@ final _basicToolPattern = RegExp( final _examplePattern = RegExp(r'{@example\s+([^}]+)}'); +final _macroRegExp = RegExp(r'{@macro\s+([^}]+)}'); + +final _htmlInjectRegExp = RegExp(r'([a-f0-9]+)'); + +final RegExp _needsPrecacheRegExp = RegExp(r'{@(template|tool|inject-html)'); + /// Features for processing directives in a documentation comment. /// -/// [processCommentWithoutTools] and [processComment] are the primary +/// [_processCommentWithoutTools] and [processComment] are the primary /// entrypoints. mixin DocumentationComment on Documentable, Warnable, Locatable, SourceCodeMixin { @@ -59,7 +67,7 @@ mixin DocumentationComment /// Process a [documentationComment], performing various actions based on /// `{@}`-style directives, except `{@tool}`, returning the processed result. - String processCommentWithoutTools(String documentationComment) { + String _processCommentWithoutTools(String documentationComment) { var docs = stripComments(documentationComment); if (!docs.contains('{@')) { _analyzeCodeBlocks(docs); @@ -79,6 +87,7 @@ mixin DocumentationComment /// Process [documentationComment], performing various actions based on /// `{@}`-style directives, returning the processed result. + @visibleForTesting Future processComment(String documentationComment) async { var docs = stripComments(documentationComment); // Must evaluate tools first, in case they insert any other directives. @@ -707,4 +716,145 @@ mixin DocumentationComment } }); } + + /// Returns the documentation for this literal element unless + /// [config.dropTextFrom] indicates it should not be returned. Macro + /// definitions are stripped, but macros themselves are not injected. This + /// is a two stage process to avoid ordering problems. + String _documentationLocal; + + String get documentationLocal => + _documentationLocal ??= _buildDocumentationLocal(); + + /// Unconditionally precache local documentation. + /// + /// Use only in factory for [PackageGraph]. + Future precacheLocalDocs() async { + _documentationLocal = await _buildDocumentationBase(); + } + + bool _needsPrecache; + bool get needsPrecache => _needsPrecache ??= + _needsPrecacheRegExp.hasMatch(documentationComment ?? ''); + + String _rawDocs; + + String _buildDocumentationLocal() => _buildDocumentationBaseSync(); + + /// Override this to add more features to the documentation builder in a + /// subclass. + String buildDocumentationAddition(String docs) => docs ?? ''; + + /// Separate from _buildDocumentationLocal for overriding. + String _buildDocumentationBaseSync() { + assert(_rawDocs == null, + 'reentrant calls to _buildDocumentation* not allowed'); + // Do not use the sync method if we need to evaluate tools or templates. + assert(!isCanonical || !needsPrecache); + if (config.dropTextFrom.contains(element.library.name)) { + _rawDocs = ''; + } else { + _rawDocs = _processCommentWithoutTools(documentationComment ?? ''); + } + _rawDocs = buildDocumentationAddition(_rawDocs); + return _rawDocs; + } + + /// Separate from _buildDocumentationLocal for overriding. Can only be + /// used as part of [PackageGraph.setUpPackageGraph]. + Future _buildDocumentationBase() async { + assert(_rawDocs == null, + 'reentrant calls to _buildDocumentation* not allowed'); + // Do not use the sync method if we need to evaluate tools or templates. + if (config.dropTextFrom.contains(element.library.name)) { + _rawDocs = ''; + } else { + _rawDocs = await processComment(documentationComment ?? ''); + } + _rawDocs = buildDocumentationAddition(_rawDocs); + return _rawDocs; + } + + /// Replace <[digest]> in API comments with + /// the contents of the HTML fragment earlier defined by the + /// {@inject-html} directive. The [digest] is a SHA1 of the contents + /// of the HTML fragment, automatically generated upon parsing the + /// {@inject-html} directive. + /// + /// This markup is generated and inserted by [_stripHtmlAndAddToIndex] when it + /// removes the HTML fragment in preparation for markdown processing. It isn't + /// meant to be used at a user level. + /// + /// Example: + /// + /// You place the fragment in a dartdoc comment: + /// + /// Some comments + /// {@inject-html} + /// <p>[HTML contents!]</p> + /// {@endtemplate} + /// More comments + /// + /// and [_stripHtmlAndAddToIndex] will replace your HTML fragment with this: + /// + /// Some comments + /// <dartdoc-html>4cc02f877240bf69855b4c7291aba8a16e5acce0</dartdoc-html> + /// More comments + /// + /// Which will render in the final HTML output as: + /// + /// Some comments + /// <p>[HTML contents!]</p> + /// More comments + /// + /// And the HTML fragment will not have been processed or changed by Markdown, + /// but just injected verbatim. + String injectHtmlFragments(String rawDocs) { + if (!config.injectHtml) return rawDocs; + + return rawDocs.replaceAllMapped(_htmlInjectRegExp, (match) { + var fragment = packageGraph.getHtmlFragment(match[1]); + if (fragment == null) { + warn(PackageWarning.unknownHtmlFragment, message: match[1]); + } + return fragment; + }); + } + + /// Replace {@macro ...} in API comments with the contents of the macro + /// + /// Syntax: + /// + /// {@macro NAME} + /// + /// Example: + /// + /// You define the template in any comment for a documentable entity like: + /// + /// {@template foo} + /// Foo contents! + /// {@endtemplate} + /// + /// and them somewhere use it like this: + /// + /// Some comments + /// {@macro foo} + /// More comments + /// + /// Which will render + /// + /// Some comments + /// Foo contents! + /// More comments + /// + String injectMacros(String rawDocs) { + return rawDocs.replaceAllMapped(_macroRegExp, (match) { + var macro = packageGraph.getMacro(match[1]); + if (macro == null) { + warn(PackageWarning.unknownMacro, message: match[1]); + } + macro = processCommentDirectives(macro ?? ''); + return macro; + }); + } } diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index 9d834dd151..6eaa00a4b6 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -34,20 +34,6 @@ import 'package:dartdoc/src/warnings.dart'; import 'package:meta/meta.dart'; import 'package:path/path.dart' as path show Context; -/// This doc may need to be processed in case it has a template or html -/// fragment. -final RegExp needsPrecacheRegExp = RegExp(r'{@(template|tool|inject-html)'); - -final _htmlInjectRegExp = RegExp(r'([a-f0-9]+)'); -@Deprecated('Public variable intended to be private; will be removed as early ' - 'as Dartdoc 1.0.0') -RegExp get htmlInjectRegExp => _htmlInjectRegExp; - -final _macroRegExp = RegExp(r'{@macro\s+([^}]+)}'); -@Deprecated('Public variable intended to be private; will be removed as early ' - 'as Dartdoc 1.0.0') -RegExp get macroRegExp => _macroRegExp; - // TODO(jcollins-g): Implement resolution per ECMA-408 4th edition, page 39 #22. /// Resolves this very rare case incorrectly by picking the closest element in /// the inheritance and interface chains from the analyzer. @@ -118,7 +104,6 @@ abstract class ModelElement extends Canonicalization final Member /*?*/ _originalMember; final Library /*?*/ _library; - String _rawDocs; Documentation __documentation; UnmodifiableListView _parameters; String _linkedName; @@ -546,59 +531,6 @@ abstract class ModelElement extends Canonicalization } } - String _buildDocumentationLocal() => _buildDocumentationBaseSync(); - - /// Override this to add more features to the documentation builder in a - /// subclass. - String buildDocumentationAddition(String docs) => docs ??= ''; - - /// Separate from _buildDocumentationLocal for overriding. - String _buildDocumentationBaseSync() { - assert(_rawDocs == null, - 'reentrant calls to _buildDocumentation* not allowed'); - // Do not use the sync method if we need to evaluate tools or templates. - assert(!isCanonical || - !needsPrecacheRegExp.hasMatch(documentationComment ?? '')); - if (config.dropTextFrom.contains(element.library.name)) { - _rawDocs = ''; - } else { - _rawDocs = processCommentWithoutTools(documentationComment ?? ''); - } - _rawDocs = buildDocumentationAddition(_rawDocs); - return _rawDocs; - } - - /// Separate from _buildDocumentationLocal for overriding. Can only be - /// used as part of [PackageGraph.setUpPackageGraph]. - Future _buildDocumentationBase() async { - assert(_rawDocs == null, - 'reentrant calls to _buildDocumentation* not allowed'); - // Do not use the sync method if we need to evaluate tools or templates. - if (config.dropTextFrom.contains(element.library.name)) { - _rawDocs = ''; - } else { - _rawDocs = await processComment(documentationComment ?? ''); - } - _rawDocs = buildDocumentationAddition(_rawDocs); - return _rawDocs; - } - - /// Returns the documentation for this literal element unless - /// [config.dropTextFrom] indicates it should not be returned. Macro - /// definitions are stripped, but macros themselves are not injected. This - /// is a two stage process to avoid ordering problems. - String _documentationLocal; - - String get documentationLocal => - _documentationLocal ??= _buildDocumentationLocal(); - - /// Returns the docs, stripped of their leading comments syntax. - @override - String get documentation { - return _injectMacros( - documentationFrom.map((e) => e.documentationLocal).join('

')); - } - Library get definingLibrary { var library = packageGraph.findButDoNotCreateLibraryFor(element); if (library == null) { @@ -735,13 +667,19 @@ abstract class ModelElement extends Canonicalization return i.enclosingElement == i.canonicalEnclosingContainer; } - String _htmlDocumentation; + /// Returns the docs, stripped of their leading comments syntax. + @override + String get documentation { + return injectMacros( + documentationFrom.map((e) => e.documentationLocal).join('

')); + } + String _documentationAsHtml; @override String get documentationAsHtml { - if (_htmlDocumentation != null) return _htmlDocumentation; - _htmlDocumentation = _injectHtmlFragments(_documentation.asHtml); - return _htmlDocumentation; + if (_documentationAsHtml != null) return _documentationAsHtml; + _documentationAsHtml = injectHtmlFragments(_elementDocumentation.asHtml); + return _documentationAsHtml; } @override @@ -824,7 +762,7 @@ abstract class ModelElement extends Canonicalization @override bool get hasExtendedDocumentation => - href != null && _documentation.hasExtendedDocs; + href != null && _elementDocumentation.hasExtendedDocs; bool get hasParameters => parameters.isNotEmpty; @@ -929,7 +867,7 @@ abstract class ModelElement extends Canonicalization String get name => _name ??= element.name; @override - String get oneLineDoc => _documentation.asOneLiner; + String get oneLineDoc => _elementDocumentation.asOneLiner; Member get originalMember => _originalMember; @@ -1022,14 +960,7 @@ abstract class ModelElement extends Canonicalization @override String computeDocumentationComment() => element.documentationComment; - /// Unconditionally precache local documentation. - /// - /// Use only in factory for [PackageGraph]. - Future precacheLocalDocs() async { - _documentationLocal = await _buildDocumentationBase(); - } - - Documentation get _documentation { + Documentation get _elementDocumentation { if (__documentation != null) return __documentation; __documentation = Documentation.forElement(this); return __documentation; @@ -1087,87 +1018,4 @@ abstract class ModelElement extends Canonicalization return modelElementRenderer.renderLinkedName(this); } - - /// Replace <[digest]> in API comments with - /// the contents of the HTML fragment earlier defined by the - /// {@inject-html} directive. The [digest] is a SHA1 of the contents - /// of the HTML fragment, automatically generated upon parsing the - /// {@inject-html} directive. - /// - /// This markup is generated and inserted by [_stripHtmlAndAddToIndex] when it - /// removes the HTML fragment in preparation for markdown processing. It isn't - /// meant to be used at a user level. - /// - /// Example: - /// - /// You place the fragment in a dartdoc comment: - /// - /// Some comments - /// {@inject-html} - /// <p>[HTML contents!]</p> - /// {@endtemplate} - /// More comments - /// - /// and [_stripHtmlAndAddToIndex] will replace your HTML fragment with this: - /// - /// Some comments - /// <dartdoc-html>4cc02f877240bf69855b4c7291aba8a16e5acce0</dartdoc-html> - /// More comments - /// - /// Which will render in the final HTML output as: - /// - /// Some comments - /// <p>[HTML contents!]</p> - /// More comments - /// - /// And the HTML fragment will not have been processed or changed by Markdown, - /// but just injected verbatim. - String _injectHtmlFragments(String rawDocs) { - if (!config.injectHtml) return rawDocs; - - return rawDocs.replaceAllMapped(_htmlInjectRegExp, (match) { - var fragment = packageGraph.getHtmlFragment(match[1]); - if (fragment == null) { - warn(PackageWarning.unknownHtmlFragment, message: match[1]); - } - return fragment; - }); - } - - /// Replace {@macro ...} in API comments with the contents of the macro - /// - /// Syntax: - /// - /// {@macro NAME} - /// - /// Example: - /// - /// You define the template in any comment for a documentable entity like: - /// - /// {@template foo} - /// Foo contents! - /// {@endtemplate} - /// - /// and them somewhere use it like this: - /// - /// Some comments - /// {@macro foo} - /// More comments - /// - /// Which will render - /// - /// Some comments - /// Foo contents! - /// More comments - /// - String _injectMacros(String rawDocs) { - return rawDocs.replaceAllMapped(_macroRegExp, (match) { - var macro = packageGraph.getMacro(match[1]); - if (macro == null) { - warn(PackageWarning.unknownMacro, message: match[1]); - } - macro = processCommentDirectives(macro ?? ''); - return macro; - }); - } } diff --git a/lib/src/model/package_graph.dart b/lib/src/model/package_graph.dart index 07b26ef911..26210a2d7d 100644 --- a/lib/src/model/package_graph.dart +++ b/lib/src/model/package_graph.dart @@ -135,8 +135,7 @@ class PackageGraph with CommentReferable, Nameable { Iterable> precacheOneElement(ModelElement m) sync* { for (var d in m.documentationFrom.where((d) => d.documentationComment != null)) { - if (needsPrecacheRegExp.hasMatch(d.documentationComment) && - !precachedElements.contains(d)) { + if (d.needsPrecache && !precachedElements.contains(d)) { precachedElements.add(d); yield d.precacheLocalDocs(); logProgress(d.name); From 5e6ec89eb98ee7e9ded87a3320fb859166584001 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Thu, 30 Sep 2021 12:48:20 -0700 Subject: [PATCH 2/6] Continuing the crushing down of documentation handling (#2818) * Straight move * Partial * delete experiment * rebuild * moved computeDocumentationComment and documentationComment * Move more documentation comment handling * remove ??= from a cut and paste * Documentation comment move for combos * better as a getter --- .../templates.runtime_renderers.dart | 176 ++++++++++++------ lib/src/model/accessor.dart | 39 ++-- lib/src/model/container_member.dart | 2 +- lib/src/model/documentation_comment.dart | 60 ++++-- lib/src/model/enum.dart | 2 +- lib/src/model/field.dart | 7 - lib/src/model/getter_setter_combo.dart | 21 ++- lib/src/model/model_element.dart | 57 +----- lib/src/model/top_level_variable.dart | 7 - 9 files changed, 208 insertions(+), 163 deletions(-) diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index 5abfcd2d64..2b1240781b 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -68,6 +68,27 @@ class _Renderer_Accessor extends RendererBase { getters: _invisibleGetters['GetterSetterCombo']); }, ), + 'documentationComment': Property( + getValue: (CT_ c) => c.documentationComment, + renderVariable: + (CT_ c, Property self, List remainingNames) { + if (remainingNames.isEmpty) { + return self.getValue(c).toString(); + } + var name = remainingNames.first; + var nextProperty = + _Renderer_String.propertyMap().getValue(name); + return nextProperty.renderVariable(self.getValue(c), + nextProperty, [...remainingNames.skip(1)]); + }, + isNullValue: (CT_ c) => c.documentationComment == null, + renderValue: (CT_ c, RendererBase r, + List ast, StringSink sink) { + _render_String( + c.documentationComment, ast, r.template, sink, + parent: r); + }, + ), 'element': Property( getValue: (CT_ c) => c.element, renderVariable: (CT_ c, Property self, @@ -3907,6 +3928,26 @@ class _Renderer_DocumentationComment _propertyMapCache.putIfAbsent( CT_, () => { + 'documentationAsHtml': Property( + getValue: (CT_ c) => c.documentationAsHtml, + renderVariable: + (CT_ c, Property self, List remainingNames) { + if (remainingNames.isEmpty) { + return self.getValue(c).toString(); + } + var name = remainingNames.first; + var nextProperty = + _Renderer_String.propertyMap().getValue(name); + return nextProperty.renderVariable(self.getValue(c), + nextProperty, [...remainingNames.skip(1)]); + }, + isNullValue: (CT_ c) => c.documentationAsHtml == null, + renderValue: (CT_ c, RendererBase r, + List ast, StringSink sink) { + _render_String(c.documentationAsHtml, ast, r.template, sink, + parent: r); + }, + ), 'documentationComment': Property( getValue: (CT_ c) => c.documentationComment, renderVariable: @@ -3928,6 +3969,20 @@ class _Renderer_DocumentationComment parent: r); }, ), + 'documentationFrom': Property( + getValue: (CT_ c) => c.documentationFrom, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'List'), + renderIterable: (CT_ c, RendererBase r, + List ast, StringSink sink) { + return c.documentationFrom.map((e) => renderSimple( + e, ast, r.template, sink, + parent: r, + getters: _invisibleGetters['DocumentationComment'])); + }, + ), 'documentationLocal': Property( getValue: (CT_ c) => c.documentationLocal, renderVariable: @@ -3948,6 +4003,19 @@ class _Renderer_DocumentationComment parent: r); }, ), + 'elementDocumentation': Property( + getValue: (CT_ c) => c.elementDocumentation, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'Documentation'), + isNullValue: (CT_ c) => c.elementDocumentation == null, + renderValue: (CT_ c, RendererBase r, + List ast, StringSink sink) { + renderSimple(c.elementDocumentation, ast, r.template, sink, + parent: r, getters: _invisibleGetters['Documentation']); + }, + ), 'fullyQualifiedNameWithoutLibrary': Property( getValue: (CT_ c) => c.fullyQualifiedNameWithoutLibrary, renderVariable: @@ -5865,17 +5933,39 @@ class _Renderer_GetterSetterCombo extends RendererBase { parent: r); }, ), + 'documentationComment': Property( + getValue: (CT_ c) => c.documentationComment, + renderVariable: + (CT_ c, Property self, List remainingNames) { + if (remainingNames.isEmpty) { + return self.getValue(c).toString(); + } + var name = remainingNames.first; + var nextProperty = + _Renderer_String.propertyMap().getValue(name); + return nextProperty.renderVariable(self.getValue(c), + nextProperty, [...remainingNames.skip(1)]); + }, + isNullValue: (CT_ c) => c.documentationComment == null, + renderValue: (CT_ c, RendererBase r, + List ast, StringSink sink) { + _render_String( + c.documentationComment, ast, r.template, sink, + parent: r); + }, + ), 'documentationFrom': Property( getValue: (CT_ c) => c.documentationFrom, renderVariable: (CT_ c, Property self, List remainingNames) => self.renderSimpleVariable( - c, remainingNames, 'List'), + c, remainingNames, 'List'), renderIterable: (CT_ c, RendererBase r, List ast, StringSink sink) { - return c.documentationFrom.map((e) => _render_ModelElement( + return c.documentationFrom.map((e) => renderSimple( e, ast, r.template, sink, - parent: r)); + parent: r, + getters: _invisibleGetters['DocumentationComment'])); }, ), 'enclosingElement': Property( @@ -5926,28 +6016,6 @@ class _Renderer_GetterSetterCombo extends RendererBase { self.renderSimpleVariable(c, remainingNames, 'bool'), getBool: (CT_ c) => c.getterSetterBothAvailable == true, ), - 'getterSetterDocumentationComment': Property( - getValue: (CT_ c) => c.getterSetterDocumentationComment, - renderVariable: - (CT_ c, Property self, List remainingNames) { - if (remainingNames.isEmpty) { - return self.getValue(c).toString(); - } - var name = remainingNames.first; - var nextProperty = - _Renderer_String.propertyMap().getValue(name); - return nextProperty.renderVariable(self.getValue(c), - nextProperty, [...remainingNames.skip(1)]); - }, - isNullValue: (CT_ c) => - c.getterSetterDocumentationComment == null, - renderValue: (CT_ c, RendererBase r, - List ast, StringSink sink) { - _render_String(c.getterSetterDocumentationComment, ast, - r.template, sink, - parent: r); - }, - ), 'hasAccessorsWithDocs': Property( getValue: (CT_ c) => c.hasAccessorsWithDocs, renderVariable: (CT_ c, Property self, @@ -9397,19 +9465,6 @@ class _Renderer_ModelElement extends RendererBase { getters: _invisibleGetters['CompilationUnitElement']); }, ), - 'computeDocumentationFrom': Property( - getValue: (CT_ c) => c.computeDocumentationFrom, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'List'), - renderIterable: (CT_ c, RendererBase r, - List ast, StringSink sink) { - return c.computeDocumentationFrom.map((e) => - _render_ModelElement(e, ast, r.template, sink, - parent: r)); - }, - ), 'config': Property( getValue: (CT_ c) => c.config, renderVariable: (CT_ c, Property self, @@ -9476,8 +9531,8 @@ class _Renderer_ModelElement extends RendererBase { parent: r); }, ), - 'documentationAsHtml': Property( - getValue: (CT_ c) => c.documentationAsHtml, + 'documentationComment': Property( + getValue: (CT_ c) => c.documentationComment, renderVariable: (CT_ c, Property self, List remainingNames) { if (remainingNames.isEmpty) { @@ -9489,26 +9544,14 @@ class _Renderer_ModelElement extends RendererBase { return nextProperty.renderVariable(self.getValue(c), nextProperty, [...remainingNames.skip(1)]); }, - isNullValue: (CT_ c) => c.documentationAsHtml == null, + isNullValue: (CT_ c) => c.documentationComment == null, renderValue: (CT_ c, RendererBase r, List ast, StringSink sink) { - _render_String(c.documentationAsHtml, ast, r.template, sink, + _render_String( + c.documentationComment, ast, r.template, sink, parent: r); }, ), - 'documentationFrom': Property( - getValue: (CT_ c) => c.documentationFrom, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'List'), - renderIterable: (CT_ c, RendererBase r, - List ast, StringSink sink) { - return c.documentationFrom.map((e) => _render_ModelElement( - e, ast, r.template, sink, - parent: r)); - }, - ), 'element': Property( getValue: (CT_ c) => c.element, renderVariable: (CT_ c, Property self, @@ -15207,6 +15250,27 @@ const _invisibleGetters = { 'useBaseHref' }, 'DocumentLocation': {'hashCode', 'runtimeType', 'index'}, + 'Documentation': { + 'hashCode', + 'runtimeType', + 'hasExtendedDocs', + 'asHtml', + 'asOneLiner', + 'commentRefs' + }, + 'DocumentationComment': { + 'documentationFrom', + 'documentationAsHtml', + 'elementDocumentation', + 'documentationComment', + 'hasNodoc', + 'sourceFileName', + 'fullyQualifiedNameWithoutLibrary', + 'pathContext', + 'modelElementRenderer', + 'documentationLocal', + 'needsPrecache' + }, 'Element': { 'hashCode', 'runtimeType', @@ -15415,7 +15479,7 @@ const _invisibleGetters = { 'hasAccessorsWithDocs', 'getterSetterBothAvailable', 'oneLineDoc', - 'getterSetterDocumentationComment', + 'documentationComment', 'modelType', 'isCallable', 'hasParameters', diff --git a/lib/src/model/accessor.dart b/lib/src/model/accessor.dart index 6a926eb72b..e3296ec22e 100644 --- a/lib/src/model/accessor.dart +++ b/lib/src/model/accessor.dart @@ -72,24 +72,29 @@ class Accessor extends ModelElement implements EnclosedElement { return _sourceCode; } + bool _documentationCommentComputed = false; + String _documentationComment; @override - String computeDocumentationComment() { - if (isSynthetic) { - // If we're a setter, only display something if we have something different than the getter. - // TODO(jcollins-g): modify analyzer to do this itself? - if (isGetter || - definingCombo.hasNodoc || - (isSetter && - definingCombo.hasGetter && - definingCombo.getter.documentationComment != - definingCombo.documentationComment)) { - return stripComments(definingCombo.documentationComment); - } else { - return ''; - } - } - return stripComments(super.computeDocumentationComment()); - } + String get documentationComment => _documentationCommentComputed + ? _documentationComment + : _documentationComment ??= () { + _documentationCommentComputed = true; + if (isSynthetic) { + // If we're a setter, only display something if we have something different than the getter. + // TODO(jcollins-g): modify analyzer to do this itself? + if (isGetter || + definingCombo.hasNodoc || + (isSetter && + definingCombo.hasGetter && + definingCombo.getter.documentationComment != + definingCombo.documentationComment)) { + return stripComments(definingCombo.documentationComment); + } else { + return ''; + } + } + return stripComments(super.documentationComment); + }(); @override void warn(PackageWarning kind, diff --git a/lib/src/model/container_member.dart b/lib/src/model/container_member.dart index 1898bc0ba0..e6ad58d012 100644 --- a/lib/src/model/container_member.dart +++ b/lib/src/model/container_member.dart @@ -73,7 +73,7 @@ mixin ContainerMember on ModelElement implements EnclosedElement { // TODO(jcollins-g): split Field documentation up between accessors // and resolve the pieces with different scopes. dart-lang/dartdoc#2693. // Until then, just pretend we're handling this correctly. - yield documentationFrom.first.definingLibrary; + yield (documentationFrom.first as ModelElement).definingLibrary; // TODO(jcollins-g): Wean users off of depending on canonical library // resolution. dart-lang/dartdoc#2696 if (canonicalLibrary != null) yield canonicalLibrary; diff --git a/lib/src/model/documentation_comment.dart b/lib/src/model/documentation_comment.dart index 405804dc3f..ad59825147 100644 --- a/lib/src/model/documentation_comment.dart +++ b/lib/src/model/documentation_comment.dart @@ -1,7 +1,10 @@ import 'package:args/args.dart'; import 'package:crypto/crypto.dart' as crypto; import 'package:dartdoc/src/model/documentable.dart'; +import 'package:dartdoc/src/model/documentation.dart'; +import 'package:dartdoc/src/model/inheritable.dart'; import 'package:dartdoc/src/model/locatable.dart'; +import 'package:dartdoc/src/model/model_element.dart'; import 'package:dartdoc/src/model/source_code_mixin.dart'; import 'package:dartdoc/src/render/model_element_renderer.dart'; import 'package:dartdoc/src/utils.dart'; @@ -37,23 +40,48 @@ final RegExp _needsPrecacheRegExp = RegExp(r'{@(template|tool|inject-html)'); /// entrypoints. mixin DocumentationComment on Documentable, Warnable, Locatable, SourceCodeMixin { - /// The documentation comment on the Element may be null, so memoization - /// cannot rely on the null-ness of [_documentationComment], it must be - /// more explicit. - bool _documentationCommentComputed = false; - String _documentationComment; - - String get documentationComment { - if (_documentationCommentComputed == false) { - _documentationComment = computeDocumentationComment(); - _documentationCommentComputed = true; - } - return _documentationComment; + List _documentationFrom; + + /// Returns the ModelElement(s) from which we will get documentation. + /// Can be more than one if this is a Field composing documentation from + /// multiple Accessors. + /// + /// This getter will walk up the inheritance hierarchy + /// to find docs, if the current class doesn't have docs + /// for this element. + @override + List get documentationFrom => + _documentationFrom ??= () { + if (documentationComment == null && + this is Inheritable && + (this as Inheritable).overriddenElement != null) { + return (this as Inheritable).overriddenElement.documentationFrom; + } else if (this is Inheritable && (this as Inheritable).isInherited) { + var thisInheritable = (this as Inheritable); + var fromThis = ModelElement.fromElement( + element, thisInheritable.definingEnclosingContainer.packageGraph); + return fromThis.documentationFrom; + } else { + return [this]; + } + }(); + + String _documentationAsHtml; + @override + String get documentationAsHtml { + if (_documentationAsHtml != null) return _documentationAsHtml; + _documentationAsHtml = _injectHtmlFragments(elementDocumentation.asHtml); + return _documentationAsHtml; + } + + Documentation _elementDocumentation; + Documentation get elementDocumentation { + if (_elementDocumentation != null) return _elementDocumentation; + _elementDocumentation = Documentation.forElement(this); + return _elementDocumentation; } - /// Implement to derive the raw documentation comment string from the - /// analyzer. - String computeDocumentationComment(); + String get documentationComment; /// Returns true if the raw documentation comment has a nodoc indication. bool get hasNodoc { @@ -809,7 +837,7 @@ mixin DocumentationComment /// /// And the HTML fragment will not have been processed or changed by Markdown, /// but just injected verbatim. - String injectHtmlFragments(String rawDocs) { + String _injectHtmlFragments(String rawDocs) { if (!config.injectHtml) return rawDocs; return rawDocs.replaceAllMapped(_htmlInjectRegExp, (match) { diff --git a/lib/src/model/enum.dart b/lib/src/model/enum.dart index 8423136c2c..b5ebb310b0 100644 --- a/lib/src/model/enum.dart +++ b/lib/src/model/enum.dart @@ -54,7 +54,7 @@ class EnumField extends Field { String get constantValueBase => _fieldRenderer.renderValue(this); @override - List get documentationFrom { + List get documentationFrom { if (name == 'values' || name == 'index') return [this]; return super.documentationFrom; } diff --git a/lib/src/model/field.dart b/lib/src/model/field.dart index 115a56d2ac..3c63c15fdb 100644 --- a/lib/src/model/field.dart +++ b/lib/src/model/field.dart @@ -136,13 +136,6 @@ class Field extends ModelElement return allFeatures; } - @override - String computeDocumentationComment() { - var docs = getterSetterDocumentationComment; - if (docs.isEmpty) return field.documentationComment; - return docs; - } - FieldElement get field => (element as FieldElement); @override diff --git a/lib/src/model/getter_setter_combo.dart b/lib/src/model/getter_setter_combo.dart index 134cd6c045..5074f34382 100644 --- a/lib/src/model/getter_setter_combo.dart +++ b/lib/src/model/getter_setter_combo.dart @@ -109,10 +109,10 @@ mixin GetterSetterCombo on ModelElement { @override bool get isPublic => hasPublicGetter || hasPublicSetter; - List _documentationFrom; + List _documentationFrom; @override - List get documentationFrom { + List get documentationFrom { if (_documentationFrom == null) { _documentationFrom = []; if (hasPublicGetter) { @@ -122,7 +122,7 @@ mixin GetterSetterCombo on ModelElement { } if (_documentationFrom.isEmpty || _documentationFrom.every((e) => e.documentationComment == '')) { - _documentationFrom = computeDocumentationFrom; + _documentationFrom = super.documentationFrom; } } return _documentationFrom; @@ -158,7 +158,20 @@ mixin GetterSetterCombo on ModelElement { return _oneLineDoc; } - String get getterSetterDocumentationComment { + bool _documentationCommentComputed = false; + String _documentationComment; + @override + String get documentationComment => _documentationCommentComputed + ? _documentationComment + : _documentationComment ??= () { + _documentationCommentComputed = true; + var docs = _getterSetterDocumentationComment; + if (docs.isEmpty) return element.documentationComment; + return docs; + }(); + + /// Derive a synthetic documentation comment using the documentation from + String get _getterSetterDocumentationComment { var buffer = StringBuffer(); // Check for synthetic before public, always, or stack overflow. diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index 6eaa00a4b6..398427610d 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -104,7 +104,6 @@ abstract class ModelElement extends Canonicalization final Member /*?*/ _originalMember; final Library /*?*/ _library; - Documentation __documentation; UnmodifiableListView _parameters; String _linkedName; @@ -491,15 +490,6 @@ abstract class ModelElement extends Canonicalization ModelElement get canonicalModelElement => _canonicalModelElement ??= buildCanonicalModelElement(); - List _documentationFrom; - - // TODO(jcollins-g): untangle when mixins can call super - @override - List get documentationFrom { - _documentationFrom ??= computeDocumentationFrom; - return _documentationFrom; - } - bool get hasSourceHref => sourceHref.isNotEmpty; String _sourceHref; @@ -508,29 +498,6 @@ abstract class ModelElement extends Canonicalization return _sourceHref; } - /// Returns the ModelElement(s) from which we will get documentation. - /// Can be more than one if this is a Field composing documentation from - /// multiple Accessors. - /// - /// This getter will walk up the inheritance hierarchy - /// to find docs, if the current class doesn't have docs - /// for this element. - List get computeDocumentationFrom { - if (documentationComment == null && - _canOverride && - this is Inheritable && - (this as Inheritable).overriddenElement != null) { - return (this as Inheritable).overriddenElement.documentationFrom; - } else if (this is Inheritable && (this as Inheritable).isInherited) { - var thisInheritable = (this as Inheritable); - var fromThis = ModelElement.fromElement( - element, thisInheritable.definingEnclosingContainer.packageGraph); - return fromThis.documentationFrom; - } else { - return [this]; - } - } - Library get definingLibrary { var library = packageGraph.findButDoNotCreateLibraryFor(element); if (library == null) { @@ -674,14 +641,6 @@ abstract class ModelElement extends Canonicalization documentationFrom.map((e) => e.documentationLocal).join('

')); } - String _documentationAsHtml; - @override - String get documentationAsHtml { - if (_documentationAsHtml != null) return _documentationAsHtml; - _documentationAsHtml = injectHtmlFragments(_elementDocumentation.asHtml); - return _documentationAsHtml; - } - @override Element get element => _element; @@ -762,7 +721,7 @@ abstract class ModelElement extends Canonicalization @override bool get hasExtendedDocumentation => - href != null && _elementDocumentation.hasExtendedDocs; + href != null && elementDocumentation.hasExtendedDocs; bool get hasParameters => parameters.isNotEmpty; @@ -867,7 +826,7 @@ abstract class ModelElement extends Canonicalization String get name => _name ??= element.name; @override - String get oneLineDoc => _elementDocumentation.asOneLiner; + String get oneLineDoc => elementDocumentation.asOneLiner; Member get originalMember => _originalMember; @@ -958,25 +917,15 @@ abstract class ModelElement extends Canonicalization } @override - String computeDocumentationComment() => element.documentationComment; - - Documentation get _elementDocumentation { - if (__documentation != null) return __documentation; - __documentation = Documentation.forElement(this); - return __documentation; - } + String get documentationComment => element.documentationComment; String _sourceCode; - @override String get sourceCode { return _sourceCode ??= _sourceCodeRenderer.renderSourceCode(super.sourceCode); } - bool get _canOverride => - element is ClassMemberElement || element is PropertyAccessorElement; - @override int compareTo(dynamic other) { if (other is ModelElement) { diff --git a/lib/src/model/top_level_variable.dart b/lib/src/model/top_level_variable.dart index 3046a60b77..801bead338 100644 --- a/lib/src/model/top_level_variable.dart +++ b/lib/src/model/top_level_variable.dart @@ -77,13 +77,6 @@ class TopLevelVariable extends ModelElement @override Set get features => {...super.features, ...comboFeatures}; - @override - String computeDocumentationComment() { - var docs = getterSetterDocumentationComment; - if (docs.isEmpty) return _variable.documentationComment; - return docs; - } - @override String get fileName => '${isConst ? '$name-constant' : name}.$fileType'; From 590edba2e4b59a17079aafd64348c944a6dd835d Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Fri, 1 Oct 2021 12:09:57 -0700 Subject: [PATCH 3/6] Remove all deprecated bits in preparation for next release (#2821) * Remove all deprecated bits in preparation for next release * make some things final --- lib/dartdoc.dart | 19 -------- .../templates.runtime_renderers.dart | 43 +------------------ lib/src/io_utils.dart | 11 ----- lib/src/model/canonicalization.dart | 34 +-------------- lib/src/model/categorization.dart | 4 -- lib/src/model/category.dart | 21 +-------- lib/src/model/inheriting_container.dart | 5 --- lib/src/model/library.dart | 13 ------ lib/src/model/package.dart | 13 ------ lib/src/model/package_graph.dart | 11 ----- lib/src/source_linker.dart | 3 -- test/end2end/dartdoc_test.dart | 4 -- test/package_test.dart | 6 --- 13 files changed, 6 insertions(+), 181 deletions(-) diff --git a/lib/dartdoc.dart b/lib/dartdoc.dart index c5678fd469..e3fbeb5f03 100644 --- a/lib/dartdoc.dart +++ b/lib/dartdoc.dart @@ -141,20 +141,6 @@ class Dartdoc { // ignore: unnecessary_getters_setters set generator(Generator newGenerator) => _generator = newGenerator; - /// An asynchronous factory method that builds Dartdoc's file writers - /// and returns a Dartdoc object with them. - @Deprecated('Prefer fromContext() instead') - static Future withDefaultGenerators( - DartdocGeneratorOptionContext config, - PackageBuilder packageBuilder, - ) async { - return Dartdoc._( - config, - await initHtmlGenerator(config), - packageBuilder, - ); - } - /// Asynchronous factory method that builds Dartdoc with an empty generator. static Future withEmptyGenerator( DartdocOptionContext config, @@ -193,15 +179,10 @@ class Dartdoc { Stream get onCheckProgress => _onCheckProgress.stream; - @Deprecated('Will be removed in 4.0.0. ' - 'Use the return value from generateDocsBase instead.') - PackageGraph packageGraph; - @visibleForTesting Future generateDocsBase() async { var stopwatch = Stopwatch()..start(); var packageGraph = await packageBuilder.buildPackageGraph(); - this.packageGraph = packageGraph; var seconds = stopwatch.elapsedMilliseconds / 1000.0; var libs = packageGraph.libraries.length; logInfo("Initialized dartdoc with $libs librar${libs == 1 ? 'y' : 'ies'} " diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index 2b1240781b..f807f8b932 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -1138,26 +1138,6 @@ class _Renderer_Category extends RendererBase { parent: r); }, ), - 'fileType': Property( - getValue: (CT_ c) => c.fileType, - renderVariable: - (CT_ c, Property self, List remainingNames) { - if (remainingNames.isEmpty) { - return self.getValue(c).toString(); - } - var name = remainingNames.first; - var nextProperty = - _Renderer_String.propertyMap().getValue(name); - return nextProperty.renderVariable(self.getValue(c), - nextProperty, [...remainingNames.skip(1)]); - }, - isNullValue: (CT_ c) => c.fileType == null, - renderValue: (CT_ c, RendererBase r, - List ast, StringSink sink) { - _render_String(c.fileType, ast, r.template, sink, - parent: r); - }, - ), 'fullyQualifiedName': Property( getValue: (CT_ c) => c.fullyQualifiedName, renderVariable: @@ -7373,18 +7353,6 @@ class _Renderer_Library extends RendererBase { parent: r)); }, ), - 'allOriginalModelElementNames': Property( - getValue: (CT_ c) => c.allOriginalModelElementNames, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'Iterable'), - renderIterable: (CT_ c, RendererBase r, - List ast, StringSink sink) { - return c.allOriginalModelElementNames.map((e) => - _render_String(e, ast, r.template, sink, parent: r)); - }, - ), 'canonicalFor': Property( getValue: (CT_ c) => c.canonicalFor, renderVariable: (CT_ c, Property self, @@ -11196,13 +11164,6 @@ class _Renderer_Package extends RendererBase { self.renderSimpleVariable(c, remainingNames, 'bool'), getBool: (CT_ c) => c.hasDocumentation == true, ), - 'hasDocumentationFile': Property( - getValue: (CT_ c) => c.hasDocumentationFile, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable(c, remainingNames, 'bool'), - getBool: (CT_ c) => c.hasDocumentationFile == true, - ), 'hasDocumentedCategories': Property( getValue: (CT_ c) => c.hasDocumentedCategories, renderVariable: (CT_ c, Property self, @@ -11594,7 +11555,7 @@ class _Renderer_Package extends RendererBase { } } -String renderIndex(PackageTemplateData context, Template template) { +String renderError(PackageTemplateData context, Template template) { var buffer = StringBuffer(); _render_PackageTemplateData(context, template.ast, template, buffer); return buffer.toString(); @@ -11796,7 +11757,7 @@ class _Renderer_PackageTemplateData extends RendererBase { } } -String renderError(PackageTemplateData context, Template template) { +String renderIndex(PackageTemplateData context, Template template) { var buffer = StringBuffer(); _render_PackageTemplateData(context, template.ast, template, buffer); return buffer.toString(); diff --git a/lib/src/io_utils.dart b/lib/src/io_utils.dart index 0cf7693ad4..418937e367 100644 --- a/lib/src/io_utils.dart +++ b/lib/src/io_utils.dart @@ -108,17 +108,6 @@ String getFileNameFor(String name) => '${name.replaceAll(_libraryNameRegExp, '-')}.html'; final _libraryNameRegExp = RegExp('[.:]'); -@Deprecated('Public variable intended to be private; will be removed as early ' - 'as Dartdoc 1.0.0') -RegExp get libraryNameRegexp => _libraryNameRegExp; - -@Deprecated('Public variable intended to be private; will be removed as early ' - 'as Dartdoc 1.0.0') -final RegExp partOfRegexp = RegExp('part of '); - -@Deprecated('Public variable intended to be private; will be removed as early ' - 'as Dartdoc 1.0.0') -final RegExp newLinePartOfRegexp = RegExp('\npart of '); typedef TaskQueueClosure = Future Function(); diff --git a/lib/src/model/canonicalization.dart b/lib/src/model/canonicalization.dart index b22a9e6e9c..8b1848b5fb 100644 --- a/lib/src/model/canonicalization.dart +++ b/lib/src/model/canonicalization.dart @@ -26,7 +26,7 @@ abstract class Canonicalization implements Locatable, Documentable { } ScoredCandidate _scoreElementWithLibrary(Library lib) { - var scoredCandidate = ScoredCandidate(this, lib); + var scoredCandidate = ScoredCandidate(lib); Iterable resplit(Set items) sync* { for (var item in items) { for (var subItem in item.split('_')) { @@ -70,12 +70,6 @@ abstract class Canonicalization implements Locatable, Documentable { scoreBoost, 'element location parts start with parts of name'); return scoredCandidate; } - - @Deprecated( - 'Public method intended to be private; will be removed as early as ' - 'Dartdoc 1.0.0') - ScoredCandidate scoreElementWithLibrary(Library lib) => - _scoreElementWithLibrary(lib); } /// This class represents the score for a particular element; how likely @@ -83,31 +77,13 @@ abstract class Canonicalization implements Locatable, Documentable { class ScoredCandidate implements Comparable { final List _reasons = []; - @Deprecated( - 'Public field intended to be private; will be removed as early as ' - 'Dartdoc 1.0.0') - List get reasons => _reasons; - - @Deprecated( - 'Public field intended to be private; will be removed as early as ' - 'Dartdoc 1.0.0') - set reasons(List value) => reasons = value; - - /// The canonicalization element being scored. - final Canonicalization _element; - - @Deprecated( - 'Public getter intended to be private; will be removed as early as ' - 'Dartdoc 1.0.0') - Canonicalization get element => _element; - final Library library; /// The score accumulated so far. Higher means it is more likely that this /// is the intended canonical Library. double score = 0.0; - ScoredCandidate(this._element, this.library); + ScoredCandidate(this.library); void _alterScore(double scoreDelta, String reason) { score += scoreDelta; @@ -117,12 +93,6 @@ class ScoredCandidate implements Comparable { } } - @Deprecated( - 'Public method intended to be private; will be removed as early as ' - 'Dartdoc 1.0.0') - void alterScore(double scoreDelta, String reason) => - _alterScore(scoreDelta, reason); - @override int compareTo(ScoredCandidate other) { //assert(element == other.element); diff --git a/lib/src/model/categorization.dart b/lib/src/model/categorization.dart index 5652e1209f..d693934016 100644 --- a/lib/src/model/categorization.dart +++ b/lib/src/model/categorization.dart @@ -8,10 +8,6 @@ final RegExp _categoryRegExp = RegExp( r'[ ]*{@(api|category|subCategory|image|samples) (.+?)}[ ]*\n?', multiLine: true); -@Deprecated('Public variable intended to be private; will be removed as early ' - 'as Dartdoc 1.0.0') -RegExp get categoryRegexp => _categoryRegExp; - /// Mixin implementing dartdoc categorization for ModelElements. abstract class Categorization implements ModelElement { @override diff --git a/lib/src/model/category.dart b/lib/src/model/category.dart index 02e3d96a7a..79fefac413 100644 --- a/lib/src/model/category.dart +++ b/lib/src/model/category.dart @@ -25,30 +25,18 @@ class Category extends Nameable Indexable implements Documentable { /// All libraries in [libraries] must come from [package]. - // TODO(srawlins): To make final, remove public getter, setter, rename to be - // public, and add `final` modifier. - Package _package; + final Package _package; @override Package get package => _package; - @Deprecated('Field intended to be final; setter will be removed as early as ' - 'Dartdoc 1.0.0') - set package(Package value) => _package = value; - final String _name; - // TODO(srawlins): To make final, remove public getter, setter, rename to be - // public, and add `final` modifier. - DartdocOptionContext _config; + final DartdocOptionContext _config; @override DartdocOptionContext get config => _config; - @Deprecated('Field intended to be final; setter will be removed as early as ' - 'Dartdoc 1.0.0') - set config(DartdocOptionContext value) => _config = value; - final Set _allItems = {}; final List _classes = []; @@ -140,11 +128,6 @@ class Category extends Nameable String get _fileType => package.fileType; - @Deprecated( - 'Public field intended to be private; will be removed as early as ' - 'Dartdoc 1.0.0') - String get fileType => _fileType; - String get filePath => 'topics/$name-topic.$_fileType'; @override diff --git a/lib/src/model/inheriting_container.dart b/lib/src/model/inheriting_container.dart index e4ac7fbc4b..d98930840b 100644 --- a/lib/src/model/inheriting_container.dart +++ b/lib/src/model/inheriting_container.dart @@ -359,11 +359,6 @@ abstract class InheritingContainer extends Container .map((et) => (et.modelElement as InheritingContainer)) .contains(other); - @Deprecated( - 'Public method intended to be private; will be removed as early as ' - 'Dartdoc 1.0.0') - bool isInheritingFrom(InheritingContainer other) => _isInheritingFrom(other); - DefinedElementType _modelType; @override diff --git a/lib/src/model/library.dart b/lib/src/model/library.dart index 0647cb66ea..0df92b185f 100644 --- a/lib/src/model/library.dart +++ b/lib/src/model/library.dart @@ -112,13 +112,6 @@ class Library extends ModelElement with Categorization, TopLevelContainer { ]); } - @Deprecated( - 'Public method intended to be private; will be removed as early as ' - 'Dartdoc 1.0.0') - static Iterable getDefinedElements( - CompilationUnitElement compilationUnit) => - _getDefinedElements(compilationUnit); - /// Allow scope for Libraries. @override Scope get scope => element.scope; @@ -171,12 +164,6 @@ class Library extends ModelElement with Categorization, TopLevelContainer { return __allOriginalModelElementNames; } - @Deprecated( - 'Public getter intended to be private; will be removed as early as ' - 'Dartdoc 1.0.0') - Iterable get allOriginalModelElementNames => - _allOriginalModelElementNames; - @override CharacterLocation get characterLocation { if (element.nameOffset == -1) { diff --git a/lib/src/model/package.dart b/lib/src/model/package.dart index 327207a6b8..a2e30dd72f 100644 --- a/lib/src/model/package.dart +++ b/lib/src/model/package.dart @@ -15,10 +15,6 @@ import 'package:meta/meta.dart'; import 'package:path/path.dart' as path show Context; import 'package:pub_semver/pub_semver.dart'; -@Deprecated('Public variable intended to be private; will be removed as early ' - 'as Dartdoc 1.0.0') -RegExp get substituteNameVersion => Package._substituteNameVersion; - // All hrefs are emitted as relative paths from the output root. We are unable // to compute them from the page we are generating, and many properties computed // using hrefs are memoized anyway. To build complete relative hrefs, we emit @@ -31,11 +27,6 @@ RegExp get substituteNameVersion => Package._substituteNameVersion; @internal const String htmlBasePlaceholder = '\%\%__HTMLBASE_dartdoc_internal__\%\%'; -@Deprecated('Public variable intended to be private; will be removed as early ' - 'as Dartdoc 1.0.0') -// ignore: non_constant_identifier_names -const String HTMLBASE_PLACEHOLDER = htmlBasePlaceholder; - /// A [LibraryContainer] that contains [Library] objects related to a particular /// package. class Package extends LibraryContainer @@ -142,10 +133,6 @@ class Package extends LibraryContainer File /*?*/ _documentationFile; - @Deprecated( - 'Instead use [documentationFile] which will be `null` if this package does not have one.') - bool get hasDocumentationFile => documentationFile != null; - File /*?*/ get documentationFile => _documentationFile ??= packageMeta.getReadmeContents(); diff --git a/lib/src/model/package_graph.dart b/lib/src/model/package_graph.dart index 26210a2d7d..2ce71b6d29 100644 --- a/lib/src/model/package_graph.dart +++ b/lib/src/model/package_graph.dart @@ -53,17 +53,6 @@ class PackageGraph with CommentReferable, Nameable { @override Element get element => null; - @Deprecated('Use with [PackageGraph.uninitialized] instead') - // ignore: non_constant_identifier_names - factory PackageGraph.UninitializedPackageGraph( - DartdocOptionContext config, - DartSdk sdk, - bool hasEmbedderSdk, - RendererFactory rendererFactory, - PackageMetaProvider packageMetaProvider) => - PackageGraph.uninitialized( - config, sdk, hasEmbedderSdk, rendererFactory, packageMetaProvider); - /// Call during initialization to add a library to this [PackageGraph]. /// /// Libraries added in this manner are assumed to be part of documented diff --git a/lib/src/source_linker.dart b/lib/src/source_linker.dart index 26d07329c5..222e72027b 100644 --- a/lib/src/source_linker.dart +++ b/lib/src/source_linker.dart @@ -12,9 +12,6 @@ import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; final _uriTemplateRegExp = RegExp(r'(%[frl]%)'); -@Deprecated('Public variable intended to be private; will be removed as early ' - 'as Dartdoc 1.0.0') -RegExp get uriTemplateRegexp => _uriTemplateRegExp; abstract class SourceLinkerOptionContext implements DartdocOptionContextBase { List get linkToSourceExcludes => diff --git a/test/end2end/dartdoc_test.dart b/test/end2end/dartdoc_test.dart index 640f4b1218..f64eec2c16 100644 --- a/test/end2end/dartdoc_test.dart +++ b/test/end2end/dartdoc_test.dart @@ -257,8 +257,6 @@ void main() { var packageGraph = results.packageGraph; var p = packageGraph.defaultPackage; expect(p.name, 'test_package'); - // ignore: deprecated_member_use_from_same_package - expect(p.hasDocumentationFile, isTrue); expect(p.documentationFile, isNotNull); // Total number of public libraries in test_package. // +2 since we are not manually excluding anything. @@ -305,8 +303,6 @@ void main() { var p = results.packageGraph; expect(p.defaultPackage.name, 'sky_engine'); - // ignore: deprecated_member_use_from_same_package - expect(p.defaultPackage.hasDocumentationFile, isFalse); expect(p.defaultPackage.documentationFile, isNull); expect(p.libraries, hasLength(3)); expect(p.libraries.map((lib) => lib.name).contains('dart:core'), isTrue); diff --git a/test/package_test.dart b/test/package_test.dart index ca93d97fae..d38709ff73 100644 --- a/test/package_test.dart +++ b/test/package_test.dart @@ -146,8 +146,6 @@ int x; writeToJoinedPath(['README.md'], 'Readme text.'); var packageGraph = await utils.bootBasicPackage( projectPath, packageMetaProvider, packageConfigProvider); - // ignore: deprecated_member_use_from_same_package - expect(packageGraph.defaultPackage.hasDocumentationFile, true); expect(packageGraph.defaultPackage.documentationFile, isNotNull); expect(packageGraph.defaultPackage.hasDocumentation, true); }); @@ -156,8 +154,6 @@ int x; writeToJoinedPath(['README'], 'Readme text.'); var packageGraph = await utils.bootBasicPackage( projectPath, packageMetaProvider, packageConfigProvider); - // ignore: deprecated_member_use_from_same_package - expect(packageGraph.defaultPackage.hasDocumentationFile, true); expect(packageGraph.defaultPackage.documentationFile, isNotNull); expect(packageGraph.defaultPackage.hasDocumentation, true); }); @@ -462,8 +458,6 @@ int x; projectPath, packageMetaProvider, packageConfigProvider); expect(packageGraph.defaultPackage.hasDocumentation, isFalse); - // ignore: deprecated_member_use_from_same_package - expect(packageGraph.defaultPackage.hasDocumentationFile, isFalse); expect(packageGraph.defaultPackage.documentationFile, isNull); expect(packageGraph.defaultPackage.documentation, isNull); }); From 6c1d35dbe3057045cdd70267c7fbd872cc9f1079 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Fri, 1 Oct 2021 13:30:03 -0700 Subject: [PATCH 4/6] documentationComment can now be non-nullable (#2819) * Straight move * Partial * delete experiment * rebuild * moved computeDocumentationComment and documentationComment * Move more documentation comment handling * remove ??= from a cut and paste * Documentation comment move for combos * better as a getter * Untangle synthetic combo documentation in preparing for non-null * rebuild * documentationComment can be made non-nullable * Update test.yaml to delete sdk check from beta branch * tab conversion error * correct name --- .github/workflows/test.yaml | 3 + .../templates.runtime_renderers.dart | 30 +++++++++ lib/src/model/accessor.dart | 51 ++++++++++---- lib/src/model/documentation_comment.dart | 10 ++- lib/src/model/getter_setter_combo.dart | 67 +++++++++++-------- lib/src/model/model_element.dart | 5 +- lib/src/model/package_graph.dart | 2 +- test/end2end/model_test.dart | 2 +- 8 files changed, 123 insertions(+), 47 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 79119acbc9..ecc351c991 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -36,6 +36,9 @@ jobs: job: flutter - sdk: beta job: sdk-analyzer + # TODO(jcollins-g): Delete exception as 2.15 beta 2 gets underway + - sdk: beta + job: sdk-docs steps: - name: Store date diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index f807f8b932..a7eb731441 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -165,6 +165,13 @@ class _Renderer_Accessor extends RendererBase { parent: r); }, ), + 'hasDocumentationComment': Property( + getValue: (CT_ c) => c.hasDocumentationComment, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.hasDocumentationComment == true, + ), 'href': Property( getValue: (CT_ c) => c.href, renderVariable: @@ -4018,6 +4025,13 @@ class _Renderer_DocumentationComment parent: r); }, ), + 'hasDocumentationComment': Property( + getValue: (CT_ c) => c.hasDocumentationComment, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.hasDocumentationComment == true, + ), 'hasNodoc': Property( getValue: (CT_ c) => c.hasNodoc, renderVariable: (CT_ c, Property self, @@ -6003,6 +6017,13 @@ class _Renderer_GetterSetterCombo extends RendererBase { self.renderSimpleVariable(c, remainingNames, 'bool'), getBool: (CT_ c) => c.hasAccessorsWithDocs == true, ), + 'hasDocumentationComment': Property( + getValue: (CT_ c) => c.hasDocumentationComment, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.hasDocumentationComment == true, + ), 'hasExplicitGetter': Property( getValue: (CT_ c) => c.hasExplicitGetter, renderVariable: (CT_ c, Property self, @@ -9720,6 +9741,13 @@ class _Renderer_ModelElement extends RendererBase { self.renderSimpleVariable(c, remainingNames, 'bool'), getBool: (CT_ c) => c.hasDocumentation == true, ), + 'hasDocumentationComment': Property( + getValue: (CT_ c) => c.hasDocumentationComment, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.hasDocumentationComment == true, + ), 'hasExtendedDocumentation': Property( getValue: (CT_ c) => c.hasExtendedDocumentation, renderVariable: (CT_ c, Property self, @@ -15224,6 +15252,7 @@ const _invisibleGetters = { 'documentationAsHtml', 'elementDocumentation', 'documentationComment', + 'hasDocumentationComment', 'hasNodoc', 'sourceFileName', 'fullyQualifiedNameWithoutLibrary', @@ -15441,6 +15470,7 @@ const _invisibleGetters = { 'getterSetterBothAvailable', 'oneLineDoc', 'documentationComment', + 'hasDocumentationComment', 'modelType', 'isCallable', 'hasParameters', diff --git a/lib/src/model/accessor.dart b/lib/src/model/accessor.dart index e3296ec22e..a9fb81b3ab 100644 --- a/lib/src/model/accessor.dart +++ b/lib/src/model/accessor.dart @@ -80,22 +80,49 @@ class Accessor extends ModelElement implements EnclosedElement { : _documentationComment ??= () { _documentationCommentComputed = true; if (isSynthetic) { - // If we're a setter, only display something if we have something different than the getter. - // TODO(jcollins-g): modify analyzer to do this itself? - if (isGetter || - definingCombo.hasNodoc || - (isSetter && - definingCombo.hasGetter && - definingCombo.getter.documentationComment != - definingCombo.documentationComment)) { - return stripComments(definingCombo.documentationComment); - } else { - return ''; - } + return _syntheticDocumentationComment; } return stripComments(super.documentationComment); }(); + String /*!*/ __syntheticDocumentationComment; + + /// Build a documentation comment for this accessor assuming it is synthetic. + /// Value here is not useful if [isSynthetic] is false. + String /*!*/ get _syntheticDocumentationComment => + __syntheticDocumentationComment ??= () { + if (_hasSyntheticDocumentationComment) { + return definingCombo.documentationComment ?? ''; + } + return ''; + }(); + + /// If this is a getter, assume we want synthetic documentation. + /// If the definingCombo has a nodoc tag, we want synthetic documentation + /// for a synthetic accessor just in case it is inherited somewhere + /// down the line due to split inheritance. + bool get _hasSyntheticDocumentationComment => + (isGetter || definingCombo.hasNodoc || _comboDocsAreIndependent()) && + definingCombo.hasDocumentationComment; + + // If we're a setter, and a getter exists, do not add synthetic + // documentation if the combo's documentation is actually derived + // from that getter. + bool _comboDocsAreIndependent() { + if (isSetter && definingCombo.hasGetter) { + if (definingCombo.getter.isSynthetic || + !definingCombo.documentationFrom.contains(this)) { + return true; + } + } + return false; + } + + @override + bool get hasDocumentationComment => isSynthetic + ? _hasSyntheticDocumentationComment + : element.documentationComment != null; + @override void warn(PackageWarning kind, {String message, diff --git a/lib/src/model/documentation_comment.dart b/lib/src/model/documentation_comment.dart index ad59825147..1351febb35 100644 --- a/lib/src/model/documentation_comment.dart +++ b/lib/src/model/documentation_comment.dart @@ -52,7 +52,7 @@ mixin DocumentationComment @override List get documentationFrom => _documentationFrom ??= () { - if (documentationComment == null && + if (!hasDocumentationComment && this is Inheritable && (this as Inheritable).overriddenElement != null) { return (this as Inheritable).overriddenElement.documentationFrom; @@ -81,11 +81,15 @@ mixin DocumentationComment return _elementDocumentation; } - String get documentationComment; + String /*!*/ get documentationComment; + + /// True if [this] has a synthetic/inherited or local documentation + /// comment. False otherwise. + bool get hasDocumentationComment; /// Returns true if the raw documentation comment has a nodoc indication. bool get hasNodoc { - if (documentationComment != null && + if (hasDocumentationComment && (documentationComment.contains('@nodoc') || documentationComment.contains(''))) { return true; diff --git a/lib/src/model/getter_setter_combo.dart b/lib/src/model/getter_setter_combo.dart index 5074f34382..3cce011981 100644 --- a/lib/src/model/getter_setter_combo.dart +++ b/lib/src/model/getter_setter_combo.dart @@ -161,44 +161,53 @@ mixin GetterSetterCombo on ModelElement { bool _documentationCommentComputed = false; String _documentationComment; @override - String get documentationComment => _documentationCommentComputed + String /*!*/ get documentationComment => _documentationCommentComputed ? _documentationComment : _documentationComment ??= () { _documentationCommentComputed = true; var docs = _getterSetterDocumentationComment; - if (docs.isEmpty) return element.documentationComment; + if (docs.isEmpty) return element.documentationComment ?? ''; return docs; }(); - /// Derive a synthetic documentation comment using the documentation from - String get _getterSetterDocumentationComment { - var buffer = StringBuffer(); - - // Check for synthetic before public, always, or stack overflow. - if (hasGetter && !getter.isSynthetic && getter.isPublic) { - assert(getter.documentationFrom.length == 1); - // We have to check against dropTextFrom here since documentationFrom - // doesn't yield the real elements for GetterSetterCombos. - if (!config.dropTextFrom - .contains(getter.documentationFrom.first.element.library.name)) { - var docs = getter.documentationFrom.first.documentationComment; - if (docs != null) buffer.write(docs); - } - } + @override + bool get hasDocumentationComment => + _getterSetterDocumentationComment.isNotEmpty || + element.documentationComment != null; + + String __getterSetterDocumentationComment; + + /// Derive a documentation comment for the combo by copying documentation + /// from the [getter] and/or [setter]. + String /*!*/ get _getterSetterDocumentationComment => + __getterSetterDocumentationComment ??= () { + var buffer = StringBuffer(); - if (hasSetter && !setter.isSynthetic && setter.isPublic) { - assert(setter.documentationFrom.length == 1); - if (!config.dropTextFrom - .contains(setter.documentationFrom.first.element.library.name)) { - var docs = setter.documentationFrom.first.documentationComment; - if (docs != null) { - if (buffer.isNotEmpty) buffer.write('\n\n'); - buffer.write(docs); + // Check for synthetic before public, always, or stack overflow. + if (hasGetter && !getter.isSynthetic && getter.isPublic) { + assert(getter.documentationFrom.length == 1); + var fromGetter = getter.documentationFrom.first; + // We have to check against dropTextFrom here since documentationFrom + // doesn't yield the real elements for GetterSetterCombos. + if (!config.dropTextFrom.contains(fromGetter.element.library.name)) { + if (fromGetter.hasDocumentationComment) { + buffer.write(fromGetter.documentationComment); + } + } } - } - } - return buffer.toString(); - } + + if (hasSetter && !setter.isSynthetic && setter.isPublic) { + assert(setter.documentationFrom.length == 1); + var fromSetter = setter.documentationFrom.first; + if (!config.dropTextFrom.contains(fromSetter.element.library.name)) { + if (fromSetter.hasDocumentationComment) { + if (buffer.isNotEmpty) buffer.write('\n\n'); + buffer.write(fromSetter.documentationComment); + } + } + } + return buffer.toString(); + }(); ElementType get modelType { if (hasGetter) return getter.modelType.returnType; diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index 398427610d..c18fad8cbd 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -917,7 +917,10 @@ abstract class ModelElement extends Canonicalization } @override - String get documentationComment => element.documentationComment; + String /*!*/ get documentationComment => element.documentationComment ?? ''; + + @override + bool get hasDocumentationComment => element.documentationComment != null; String _sourceCode; @override diff --git a/lib/src/model/package_graph.dart b/lib/src/model/package_graph.dart index 2ce71b6d29..16ef48c4b1 100644 --- a/lib/src/model/package_graph.dart +++ b/lib/src/model/package_graph.dart @@ -123,7 +123,7 @@ class PackageGraph with CommentReferable, Nameable { Iterable> precacheOneElement(ModelElement m) sync* { for (var d - in m.documentationFrom.where((d) => d.documentationComment != null)) { + in m.documentationFrom.where((d) => d.hasDocumentationComment)) { if (d.needsPrecache && !precachedElements.contains(d)) { precachedElements.add(d); yield d.precacheLocalDocs(); diff --git a/test/end2end/model_test.dart b/test/end2end/model_test.dart index 1a64fafc9a..871cba9c59 100644 --- a/test/end2end/model_test.dart +++ b/test/end2end/model_test.dart @@ -630,7 +630,7 @@ void main() { () { // Verify setup of the test is correct. expect(invokeToolParentDoc.isCanonical, isTrue); - expect(invokeToolParentDoc.documentationComment, isNull); + expect(invokeToolParentDoc.hasDocumentationComment, isFalse); // Error message here might look strange due to toString() on Methods, but if this // fails that means we don't have the correct invokeToolParentDoc instance. expect(invokeToolParentDoc.documentationFrom, From cefb14b764fe352932989044f1b7b7cf435aec19 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Mon, 4 Oct 2021 08:45:14 -0700 Subject: [PATCH 5/6] Stop testing beta in the bots (#2824) * disable beta * try switching on stable * stable doesn't work for a lot of things now either :-( * try enabling the main bot --- .github/workflows/test.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ecc351c991..0667f0bf27 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [dev, beta] + sdk: [dev, stable] job: [main, flutter, sdk-analyzer, packages, sdk-docs] include: - os: macos-latest @@ -32,12 +32,11 @@ jobs: # Do not try to run flutter against the "stable" sdk, # it is unlikely to work and produces uninteresting # results. - - sdk: beta + - sdk: stable job: flutter - - sdk: beta + - sdk: stable job: sdk-analyzer - # TODO(jcollins-g): Delete exception as 2.15 beta 2 gets underway - - sdk: beta + - sdk: stable job: sdk-docs steps: From 6ce99b5156d9c90e9614a8785aee84fcb310b6ce Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Mon, 4 Oct 2021 09:33:20 -0700 Subject: [PATCH 6/6] Change "dartfmt" -> "dart format". (#2822) Co-authored-by: Janice Collins --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 36f42bf20f..42ea2065bb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ yet in the issue tracker, start by opening an issue. Thanks! 2. When a change is user-facing, please add a new entry to the [changelog](https://github.com/dart-lang/dartdoc/blob/master/CHANGELOG.md) 3. Please include a test for your change. `dartdoc` has both `package:test`-style unittests as well as integration tests. To run the unittests, use `grind test`. 4. For major changes, run `grind compare-sdk-warnings` and `grind compare-flutter-warnings`, and include the summary results in your pull request. -5. Be sure to format your Dart code using `dartfmt -w`, otherwise travis will complain. +5. Be sure to format your Dart code using `dart format`, otherwise travis will complain. 6. Use `grind presubmit` before creating a pull request to quickly check for common problems. 7. Post your change via a pull request for review and integration!