From 39d0d20f5226448eaf83af84f02ed35f52b38796 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 3 Feb 2025 21:37:33 -0800 Subject: [PATCH] Migrate Constructor element model --- .../templates.runtime_renderers.dart | 84 ++++++++++++++++++- lib/src/model/constructor.dart | 79 ++++++++--------- lib/src/model/getter_setter_combo.dart | 8 +- lib/src/model/inheriting_container.dart | 2 +- lib/src/model/model_element.dart | 22 +++-- lib/src/model/nameable.dart | 9 +- test/constructors_test.dart | 48 +++++------ test/end2end/model_test.dart | 18 ++-- test/parameters_test.dart | 6 +- test/templates/class_test.dart | 2 +- test/templates/extension_type_test.dart | 5 +- 11 files changed, 187 insertions(+), 96 deletions(-) diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index fcf499fab9..df2ba774f4 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -3505,6 +3505,34 @@ class _Renderer_Constructor extends RendererBase { ); }, ), + 'element2': Property( + getValue: (CT_ c) => c.element2, + renderVariable: + (CT_ c, Property self, List remainingNames) => + self.renderSimpleVariable( + c, + remainingNames, + 'ConstructorElement2', + ), + + isNullValue: (CT_ c) => false, + + renderValue: ( + CT_ c, + RendererBase r, + List ast, + StringSink sink, + ) { + renderSimple( + c.element2, + ast, + r.template, + sink, + parent: r, + getters: _invisibleGetters['ConstructorElement2']!, + ); + }, + ), 'enclosingElement': Property( getValue: (CT_ c) => c.enclosingElement, renderVariable: ( @@ -3543,6 +3571,38 @@ class _Renderer_Constructor extends RendererBase { ); }, ), + 'fileName': Property( + getValue: (CT_ c) => c.fileName, + 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) as String, + nextProperty, + [...remainingNames.skip(1)], + ); + }, + + isNullValue: (CT_ c) => false, + + renderValue: ( + CT_ c, + RendererBase r, + List ast, + StringSink sink, + ) { + _render_String(c.fileName, ast, r.template, sink, parent: r); + }, + ), 'fullKind': Property( getValue: (CT_ c) => c.fullKind, renderVariable: ( @@ -14411,7 +14471,7 @@ class _Renderer_LibraryContainer extends RendererBase { } } -String renderLibrary(LibraryTemplateData context, Template template) { +String renderLibraryRedirect(LibraryTemplateData context, Template template) { var buffer = StringBuffer(); _render_LibraryTemplateData(context, template.ast, template, buffer); return buffer.toString(); @@ -14657,7 +14717,7 @@ class _Renderer_LibraryTemplateData extends RendererBase { } } -String renderLibraryRedirect(LibraryTemplateData context, Template template) { +String renderLibrary(LibraryTemplateData context, Template template) { var buffer = StringBuffer(); _render_LibraryTemplateData(context, template.ast, template, buffer); return buffer.toString(); @@ -20710,13 +20770,13 @@ class _Renderer_PackageTemplateData extends RendererBase { } } -String renderSearchPage(PackageTemplateData context, Template template) { +String renderIndex(PackageTemplateData context, Template template) { var buffer = StringBuffer(); _render_PackageTemplateData(context, template.ast, template, buffer); return buffer.toString(); } -String renderIndex(PackageTemplateData context, Template template) { +String renderSearchPage(PackageTemplateData context, Template template) { var buffer = StringBuffer(); _render_PackageTemplateData(context, template.ast, template, buffer); return buffer.toString(); @@ -26243,6 +26303,22 @@ const _invisibleGetters = { 'runtimeType', 'superConstructor', }, + 'ConstructorElement2': { + 'baseElement', + 'enclosingElement2', + 'firstFragment', + 'fragments', + 'hashCode', + 'isConst', + 'isDefaultConstructor', + 'isFactory', + 'isGenerative', + 'name3', + 'redirectedConstructor2', + 'returnType', + 'runtimeType', + 'superConstructor2', + }, 'ContainerModifier': { 'displayName', 'hashCode', diff --git a/lib/src/model/constructor.dart b/lib/src/model/constructor.dart index bb3cc963a6..f87f1a018f 100644 --- a/lib/src/model/constructor.dart +++ b/lib/src/model/constructor.dart @@ -2,9 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// ignore_for_file: analyzer_use_new_elements - import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/source/line_info.dart'; import 'package:dartdoc/src/element_type.dart'; import 'package:dartdoc/src/model/comment_referable.dart'; @@ -14,13 +13,19 @@ import 'package:dartdoc/src/model_utils.dart'; class Constructor extends ModelElement with ContainerMember, TypeParameters { @override - final ConstructorElement element; + // ignore: analyzer_use_new_elements + ConstructorElement get element => + // ignore: analyzer_use_new_elements + element2.firstFragment as ConstructorElement; + + @override + final ConstructorElement2 element2; - Constructor(this.element, super.library, super.packageGraph); + Constructor(this.element2, super.library, super.packageGraph); @override CharacterLocation? get characterLocation { - if (element.isSynthetic) { + if (element2.isSynthetic) { // Make warnings for a synthetic constructor refer to somewhere reasonable // since a synthetic constructor has no definition independent of the // parent class. @@ -33,11 +38,11 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters { bool get isPublic { if (!super.isPublic) return false; if (element2.hasPrivateName) return false; - var class_ = element.enclosingElement3; + var class_ = element2.enclosingElement2; // Enums cannot be explicitly constructed or extended. - if (class_ is EnumElement) return false; - if (class_ is ClassElement) { - if (element.isFactory) return true; + if (class_ is EnumElement2) return false; + if (class_ is ClassElement2) { + if (element2.isFactory) return true; if (class_.isSealed || (class_.isAbstract && class_.isFinal) || (class_.isAbstract && class_.isInterface)) { @@ -56,7 +61,12 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters { @override Container get enclosingElement => - getModelFor(element.enclosingElement3, library) as Container; + getModelFor2(element2.enclosingElement2, library) as Container; + + @override + String get fileName => + // TODO(srawlins): It would be great to use `new.html` as the file name. + isUnnamedConstructor ? '${enclosingElement.name}.html' : '$name.html'; @override String get aboveSidebarPath => enclosingElement.sidebarPath; @@ -71,39 +81,32 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters { } @override - String get fullyQualifiedName { - if (isUnnamedConstructor) return super.fullyQualifiedName; - return '${library.name}.$name'; - } + String get fullyQualifiedName => '${library.name}.$name'; @override - bool get isConst => element.isConst; + bool get isConst => element2.isConst; - bool get isUnnamedConstructor => name == enclosingElement.name; + bool get isUnnamedConstructor => element2.name3 == 'new'; - bool get isFactory => element.isFactory; + bool get isFactory => element2.isFactory; @override Kind get kind => Kind.constructor; - late final Callable modelType = getTypeFor(element.type, library) as Callable; + late final Callable modelType = + getTypeFor(element2.type, library) as Callable; @override - String get name { - // TODO(jcollins-g): After the old lookup code is retired, rationalize - // [name] around the conventions used in referenceChildren and replace - // code there and elsewhere with simple references to the name. - var constructorName = element.name; - if (constructorName.isEmpty) { - return enclosingElement.name; - } - return '${enclosingElement.name}.$constructorName'; - } + String get name => + // TODO(jcollins-g): After the old lookup code is retired, rationalize + // [name] around the conventions used in referenceChildren and replace + // code there and elsewhere with simple references to the name. + '${enclosingElement.name}.${element2.name3}'; @override String get nameWithGenerics { - var constructorName = element.name; - if (constructorName.isEmpty) { + var constructorName = element2.name3!; + if (constructorName == 'new') { return '${enclosingElement.name}$genericParameters'; } return '${enclosingElement.name}$genericParameters.$constructorName'; @@ -111,7 +114,7 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters { String? get shortName { if (name.contains('.')) { - return name.substring(element.enclosingElement3.name.length + 1); + return name.substring(element2.enclosingElement2.name3!.length + 1); } else { return name; } @@ -120,17 +123,17 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters { @override late final Map referenceChildren = () { // Find the element that [parameter] is _really_ referring to. - Element? dereferenceParameter(ParameterElement? parameter) => + Element2? dereferenceParameter(FormalParameterElement? parameter) => switch (parameter) { - FieldFormalParameterElement() => parameter.field, - SuperFormalParameterElement() => - dereferenceParameter(parameter.superConstructorParameter), + FieldFormalParameterElement2() => parameter.field2, + SuperFormalParameterElement2() => + dereferenceParameter(parameter.superConstructorParameter2), _ => parameter }; var parameterElements = parameters.map((parameter) { - var element = dereferenceParameter(parameter.element); - return element == null ? parameter : getModelForElement(element); + var element = dereferenceParameter(parameter.element2); + return element == null ? parameter : getModelForElement2(element); }); return { for (var element in parameterElements) element.referenceName: element, @@ -140,5 +143,5 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters { @override String get referenceName => - isUnnamedConstructor ? enclosingElement.name : element.name; + isUnnamedConstructor ? enclosingElement.name : element2.name3!; } diff --git a/lib/src/model/getter_setter_combo.dart b/lib/src/model/getter_setter_combo.dart index ace35bb0b3..0475c1d619 100644 --- a/lib/src/model/getter_setter_combo.dart +++ b/lib/src/model/getter_setter_combo.dart @@ -83,7 +83,6 @@ mixin GetterSetterCombo on ModelElement { String linkifyConstantValue(String original) { if (_constantInitializer is! InstanceCreationExpression) return original; - var constructorName = _constantInitializer.constructorName.toString(); var element = _constantInitializer.constructorName.element; if (element == null) return original; @@ -93,8 +92,11 @@ mixin GetterSetterCombo on ModelElement { // TODO(jcollins-g): this logic really should be integrated into // `Constructor`, but that's not trivial because of `linkedName`'s usage. - if (enclosingElement.name == target.name) { - return original.replaceAll(constructorName, target.linkedName); + if (target.isUnnamedConstructor) { + var parts = target.linkedNameParts; + // We don't want the `.new` representation of an unnamed constructor. + var linkedName = '${parts.tag}${enclosingElement.name}${parts.endTag}'; + return original.replaceAll(enclosingElement.name, linkedName); } return original.replaceAll('${enclosingElement.name}.${target.name}', '${enclosingElement.linkedName}.${target.linkedName}'); diff --git a/lib/src/model/inheriting_container.dart b/lib/src/model/inheriting_container.dart index 7cd552fc86..0f8c0ec797 100644 --- a/lib/src/model/inheriting_container.dart +++ b/lib/src/model/inheriting_container.dart @@ -28,7 +28,7 @@ mixin Constructable implements InheritingContainer { @override late final List publicConstructorsSorted = - constructors.wherePublic.toList(growable: false)..sort(); + constructors.wherePublic.toList(growable: false)..sort(byName); @override @visibleForOverriding diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index 87fe643ba4..387a05157c 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -314,7 +314,7 @@ abstract class ModelElement ExtensionTypeElement() => ExtensionType(e, library, packageGraph), FunctionElement() => ModelFunction( e.asElement2 as TopLevelFunctionElement, library, packageGraph), - ConstructorElement() => Constructor(e, library, packageGraph), + ConstructorElement() => Constructor(e.asElement2, library, packageGraph), GenericFunctionTypeElement() => ModelFunctionTypedef( e.asElement2 as FunctionTypedElement2, library, packageGraph), TypeAliasElement(aliasedType: FunctionType()) => @@ -370,7 +370,8 @@ abstract class ModelElement if (e.enclosingElement3 is ExtensionElement || e.enclosingElement3 is InterfaceElement) { if (enclosingContainer == null || enclosingContainer is Extension) { - return ContainerAccessor(e.asElement2, library, packageGraph, enclosingContainer); + return ContainerAccessor( + e.asElement2, library, packageGraph, enclosingContainer); } return ContainerAccessor.inherited( @@ -688,7 +689,14 @@ abstract class ModelElement @override Library get library => _library; + /// The name of this element, wrapped in an HTML link (an `` tag) if [href] + /// is non-`null`. late final String linkedName = () { + var parts = linkedNameParts; + return '${parts.tag}${parts.text}${parts.endTag}'; + }(); + + ({String tag, String text, String endTag}) get linkedNameParts { // If `name` is empty, we probably have the wrong Element association or // there's an analyzer issue. assert(name.isNotEmpty || @@ -701,12 +709,16 @@ abstract class ModelElement if (isPublicAndPackageDocumented) { warn(PackageWarning.noCanonicalFound); } - return htmlEscape.convert(name); + return (tag: '', text: htmlEscape.convert(name), endTag: ''); } var cssClass = isDeprecated ? ' class="deprecated"' : ''; - return '$displayName'; - }(); + return ( + tag: '', + text: displayName, + endTag: '' + ); + } ParameterRenderer get _parameterRenderer => const ParameterRendererHtml(); diff --git a/lib/src/model/nameable.dart b/lib/src/model/nameable.dart index 36ddb4935d..5b8480c5b6 100644 --- a/lib/src/model/nameable.dart +++ b/lib/src/model/nameable.dart @@ -12,6 +12,7 @@ import 'package:analyzer/src/utilities/extensions/element.dart'; import 'package:collection/collection.dart'; import 'package:dartdoc/src/element_type.dart'; import 'package:dartdoc/src/model/accessor.dart'; +import 'package:dartdoc/src/model/constructor.dart'; import 'package:dartdoc/src/model/container.dart'; import 'package:dartdoc/src/model/library.dart'; import 'package:dartdoc/src/model/model_element.dart'; @@ -121,7 +122,7 @@ mixin Nameable { enclosingContainer: enclosingContainer, ); - /// Returns the [ModelElement] for [element], instantiating it if needed. + /// Returns the [ModelElement] for [element], instantiating it if needed. /// /// A convenience method for [ModelElement.forPropertyInducingElement], see /// its documentation. @@ -155,6 +156,12 @@ int byName(Nameable a, Nameable b) { return compareAsciiLowerCaseNatural(a.displayName, b.displayName); } + if (a is Constructor && b is Constructor) { + var aName = a.name.replaceFirst('.new', ''); + var bName = b.name.replaceFirst('.new', ''); + return compareAsciiLowerCaseNatural(aName, bName); + } + var stringCompare = compareAsciiLowerCaseNatural(a.name, b.name); if (stringCompare != 0) { return stringCompare; diff --git a/test/constructors_test.dart b/test/constructors_test.dart index 81f744910b..2e2d74ce4f 100644 --- a/test/constructors_test.dart +++ b/test/constructors_test.dart @@ -27,9 +27,8 @@ abstract final class C { } '''); var c = library.classes.named('C').constructors.first; - expect(c.name, equals('C')); - // TODO(srawlins): This should be `constructors.C.new`. - expect(c.fullyQualifiedName, 'constructors.C.C'); + expect(c.name, equals('C.new')); + expect(c.fullyQualifiedName, 'constructors.C.new'); expect(c.isPublic, isTrue); expect(c.documentationAsHtml, '

Constructor.

'); } @@ -42,9 +41,8 @@ abstract final class C { } '''); var c = library.classes.named('C').constructors.first; - expect(c.name, equals('C')); - // TODO(srawlins): This should be `constructors.C.new`. - expect(c.fullyQualifiedName, 'constructors.C.C'); + expect(c.name, equals('C.new')); + expect(c.fullyQualifiedName, 'constructors.C.new'); expect(c.isPublic, isFalse); expect(c.documentationAsHtml, '

Constructor.

'); } @@ -57,9 +55,8 @@ abstract interface class C { } '''); var c = library.classes.named('C').constructors.first; - expect(c.name, equals('C')); - // TODO(srawlins): This should be `constructors.C.new`. - expect(c.fullyQualifiedName, 'constructors.C.C'); + expect(c.name, equals('C.new')); + expect(c.fullyQualifiedName, 'constructors.C.new'); expect(c.isPublic, isFalse); expect(c.documentationAsHtml, '

Constructor.

'); } @@ -86,7 +83,7 @@ class _C { } '''); var c = library.classes.named('_C').constructors.first; - expect(c.name, equals('_C')); + expect(c.name, equals('_C.new')); expect(c.isPublic, isFalse); expect(c.documentationAsHtml, '

Constructor.

'); } @@ -96,7 +93,7 @@ class _C { class C {} '''); var c = library.classes.named('C').constructors.first; - expect(c.name, equals('C')); + expect(c.name, equals('C.new')); expect(c.isPublic, isTrue); expect(c.documentationAsHtml, ''); } @@ -123,7 +120,7 @@ class C { } '''); var c = library.classes.named('C').constructors.first; - expect(c.name, equals('C')); + expect(c.name, equals('C.new')); expect(c.isPublic, isTrue); expect(c.documentationAsHtml, '

Constructor.

'); } @@ -136,9 +133,8 @@ class C { } '''); var c = library.classes.named('C').constructors.first; - expect(c.name, equals('C')); - // TODO(srawlins): This should be `constructors.C.new`. - expect(c.fullyQualifiedName, 'constructors.C.C'); + expect(c.name, equals('C.new')); + expect(c.fullyQualifiedName, 'constructors.C.new'); expect(c.isPublic, isTrue); expect(c.documentationAsHtml, '

Constructor.

'); } @@ -151,7 +147,7 @@ sealed class C { } '''); var c = library.classes.named('C').constructors.first; - expect(c.name, equals('C')); + expect(c.name, equals('C.new')); expect(c.isPublic, isFalse); expect(c.documentationAsHtml, '

Constructor.

'); } @@ -180,9 +176,8 @@ enum E { } '''); var e = library.enums.named('E').constructors.first; - expect(e.name, equals('E')); - // TODO(srawlins): This should be `constructors.E.new`. - expect(e.fullyQualifiedName, 'constructors.E.E'); + expect(e.name, equals('E.new')); + expect(e.fullyQualifiedName, 'constructors.E.new'); expect(e.isPublic, isFalse); expect(e.documentationAsHtml, '

Constructor.

'); } @@ -196,7 +191,6 @@ extension type ET(int it) { '''); var etNamed = library.extensionTypes.named('ET').constructors.named('ET.named'); - expect(etNamed.name, equals('ET.named')); expect(etNamed.fullyQualifiedName, 'constructors.ET.named'); expect(etNamed.isPublic, isTrue); expect(etNamed.documentationAsHtml, '

Constructor.

'); @@ -208,7 +202,6 @@ extension type ET.named(int it) {} '''); var etNamed = library.extensionTypes.named('ET').constructors.named('ET.named'); - expect(etNamed.name, equals('ET.named')); expect(etNamed.fullyQualifiedName, 'constructors.ET.named'); expect(etNamed.isPublic, isTrue); } @@ -217,10 +210,8 @@ extension type ET.named(int it) {} var library = await bootPackageWithLibrary(''' extension type ET(int it) {} '''); - var et = library.extensionTypes.named('ET').constructors.named('ET'); - expect(et.name, equals('ET')); - // TODO(srawlins): This should be `constructors.ET.new`. - expect(et.fullyQualifiedName, 'constructors.ET.ET'); + var et = library.extensionTypes.named('ET').constructors.named('ET.new'); + expect(et.fullyQualifiedName, 'constructors.ET.new'); expect(et.isPublic, isTrue); } @@ -231,10 +222,9 @@ extension type ET.named(int it) { ET(this.it); } '''); - var etNamed = library.extensionTypes.named('ET').constructors.named('ET'); - expect(etNamed.name, equals('ET')); - // TODO(srawlins): This should be `constructors.ET.new`. - expect(etNamed.fullyQualifiedName, 'constructors.ET.ET'); + var etNamed = + library.extensionTypes.named('ET').constructors.named('ET.new'); + expect(etNamed.fullyQualifiedName, 'constructors.ET.new'); expect(etNamed.isPublic, isTrue); expect(etNamed.documentationAsHtml, '

Constructor.

'); } diff --git a/test/end2end/model_test.dart b/test/end2end/model_test.dart index b8745b7f5c..b49f7f976f 100644 --- a/test/end2end/model_test.dart +++ b/test/end2end/model_test.dart @@ -2414,7 +2414,7 @@ void main() async { aNonDefaultConstructor = baseForDocComments.constructors .named('BaseForDocComments.aNonDefaultConstructor'); defaultConstructor = - baseForDocComments.constructors.named('BaseForDocComments'); + baseForDocComments.constructors.named('BaseForDocComments.new'); somethingShadowyParameter = defaultConstructor.parameters.named('somethingShadowy'); initializeMe = baseForDocComments.allFields.named('initializeMe'); @@ -2473,7 +2473,7 @@ void main() async { anotherConstructor = FactoryConstructorThings.constructors .named('FactoryConstructorThings.anotherConstructor'); factoryConstructorThingsDefault = FactoryConstructorThings.constructors - .named('FactoryConstructorThings'); + .named('FactoryConstructorThings.new'); aName = anotherName.parameters.named('aName'); anotherNameParameter = anotherName.parameters.named('anotherName'); @@ -3974,8 +3974,10 @@ String? topLevelFunction(int param1, bool param2, Cool coolBeans, }); test('substrings of the constant values type are not linked (#1535)', () { - expect(aName.constantValue, - 'const ExtendedShortName("hello there")'); + expect( + aName.constantValue, + 'const ExtendedShortName("hello there")', + ); }); test('constant field values are escaped', () { @@ -4040,10 +4042,10 @@ String? topLevelFunction(int param1, bool param2, Cool coolBeans, constCat = exLibrary.classes.named('ConstantCat'); constructorTester = fakeLibrary.classes.named('ConstructorTester'); constCatConstructor = constCat.constructors.first; - appleDefaultConstructor = apple.constructors.named('Apple'); + appleDefaultConstructor = apple.constructors.named('Apple.new'); appleConstructorFromString = apple.constructors.named('Apple.fromString'); constructorTesterDefault = - constructorTester.constructors.named('ConstructorTester'); + constructorTester.constructors.named('ConstructorTester.new'); constructorTesterFromSomething = constructorTester.constructors .named('ConstructorTester.fromSomething'); referToADefaultConstructor = @@ -4095,8 +4097,8 @@ String? topLevelFunction(int param1, bool param2, Cool coolBeans, test('has constructor', () { expect(appleDefaultConstructor, isNotNull); - expect(appleDefaultConstructor.name, equals('Apple')); - expect(appleDefaultConstructor.shortName, equals('Apple')); + expect(appleDefaultConstructor.name, equals('Apple.new')); + expect(appleDefaultConstructor.shortName, equals('new')); }); test('title has factory qualifier', () { diff --git a/test/parameters_test.dart b/test/parameters_test.dart index f43a6361e9..d9c3908403 100644 --- a/test/parameters_test.dart +++ b/test/parameters_test.dart @@ -251,7 +251,7 @@ class C { C(this.p); } '''); - var cConstructor = library.classes.named('C').constructors.named('C'); + var cConstructor = library.classes.named('C').constructors.named('C.new'); // There is no link, but also no wrong link or crash. expect(cConstructor.documentationAsHtml, '

Text p.

'); } @@ -264,7 +264,7 @@ class C { C(this._); } '''); - var cConstructor = library.classes.named('C').constructors.named('C'); + var cConstructor = library.classes.named('C').constructors.named('C.new'); // There is no link, but also no wrong link or crash. expect(cConstructor.documentationAsHtml, '

Text _.

'); } @@ -279,7 +279,7 @@ class D extends C { D(super._) {} } '''); - var dConstructor = library.classes.named('D').constructors.named('D'); + var dConstructor = library.classes.named('D').constructors.named('D.new'); // There is no link, but also no wrong link or crash. expect(dConstructor.documentationAsHtml, '

Text _.

'); } diff --git a/test/templates/class_test.dart b/test/templates/class_test.dart index 2e46a46a88..c70ef2bde0 100644 --- a/test/templates/class_test.dart +++ b/test/templates/class_test.dart @@ -218,7 +218,7 @@ class C { htmlLines.expectMainContentContainsAllInOrder([ matches('

Constructors

'), - matches('C'), + matches('C.new'), matches('An unnamed constructor.'), ]); } diff --git a/test/templates/extension_type_test.dart b/test/templates/extension_type_test.dart index 5c9a7cb381..4d50a24844 100644 --- a/test/templates/extension_type_test.dart +++ b/test/templates/extension_type_test.dart @@ -166,9 +166,8 @@ extension type One(int it) { htmlLines.expectMainContentContainsAllInOrder([ matches('

Constructors

'), - matches('One'), - matches('' - 'One.named'), + matches('One.new'), + matches('One.named'), matches('A named constructor.'), ]); }