Skip to content

Commit b8b63d1

Browse files
authored
Migrate Constructor element model (#3987)
1 parent a1e234e commit b8b63d1

11 files changed

+131
-91
lines changed

lib/src/generator/templates.runtime_renderers.dart

+32
Original file line numberDiff line numberDiff line change
@@ -3571,6 +3571,38 @@ class _Renderer_Constructor extends RendererBase<Constructor> {
35713571
);
35723572
},
35733573
),
3574+
'fileName': Property(
3575+
getValue: (CT_ c) => c.fileName,
3576+
renderVariable: (
3577+
CT_ c,
3578+
Property<CT_> self,
3579+
List<String> remainingNames,
3580+
) {
3581+
if (remainingNames.isEmpty) {
3582+
return self.getValue(c).toString();
3583+
}
3584+
var name = remainingNames.first;
3585+
var nextProperty = _Renderer_String.propertyMap().getValue(
3586+
name,
3587+
);
3588+
return nextProperty.renderVariable(
3589+
self.getValue(c) as String,
3590+
nextProperty,
3591+
[...remainingNames.skip(1)],
3592+
);
3593+
},
3594+
3595+
isNullValue: (CT_ c) => false,
3596+
3597+
renderValue: (
3598+
CT_ c,
3599+
RendererBase<CT_> r,
3600+
List<MustachioNode> ast,
3601+
StringSink sink,
3602+
) {
3603+
_render_String(c.fileName, ast, r.template, sink, parent: r);
3604+
},
3605+
),
35743606
'fullKind': Property(
35753607
getValue: (CT_ c) => c.fullKind,
35763608
renderVariable: (

lib/src/model/constructor.dart

+34-37
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
// ignore_for_file: analyzer_use_new_elements
6-
75
import 'package:analyzer/dart/element/element.dart';
86
import 'package:analyzer/dart/element/element2.dart';
97
import 'package:analyzer/source/line_info.dart';
@@ -17,7 +15,8 @@ import 'package:dartdoc/src/model_utils.dart';
1715

1816
class Constructor extends ModelElement with ContainerMember, TypeParameters {
1917
@override
20-
ConstructorElement get element => element2.asElement;
18+
// ignore: analyzer_use_new_elements
19+
ConstructorElement get element => element2.asElement;
2120

2221
@override
2322
final ConstructorElement2 element2;
@@ -26,7 +25,7 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters {
2625

2726
@override
2827
CharacterLocation? get characterLocation {
29-
if (element.isSynthetic) {
28+
if (element2.isSynthetic) {
3029
// Make warnings for a synthetic constructor refer to somewhere reasonable
3130
// since a synthetic constructor has no definition independent of the
3231
// parent class.
@@ -39,11 +38,11 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters {
3938
bool get isPublic {
4039
if (!super.isPublic) return false;
4140
if (element2.hasPrivateName) return false;
42-
var class_ = element.enclosingElement3;
41+
var class_ = element2.enclosingElement2;
4342
// Enums cannot be explicitly constructed or extended.
44-
if (class_ is EnumElement) return false;
45-
if (class_ is ClassElement) {
46-
if (element.isFactory) return true;
43+
if (class_ is EnumElement2) return false;
44+
if (class_ is ClassElement2) {
45+
if (element2.isFactory) return true;
4746
if (class_.isSealed ||
4847
(class_.isAbstract && class_.isFinal) ||
4948
(class_.isAbstract && class_.isInterface)) {
@@ -62,7 +61,12 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters {
6261

6362
@override
6463
Container get enclosingElement =>
65-
getModelFor(element.enclosingElement3, library) as Container;
64+
getModelFor2(element2.enclosingElement2, library) as Container;
65+
66+
@override
67+
String get fileName =>
68+
// TODO(srawlins): It would be great to use `new.html` as the file name.
69+
isUnnamedConstructor ? '${enclosingElement.name}.html' : '$name.html';
6670

6771
@override
6872
String get aboveSidebarPath => enclosingElement.sidebarPath;
@@ -77,47 +81,40 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters {
7781
}
7882

7983
@override
80-
String get fullyQualifiedName {
81-
if (isUnnamedConstructor) return super.fullyQualifiedName;
82-
return '${library.name}.$name';
83-
}
84+
String get fullyQualifiedName => '${library.name}.$name';
8485

8586
@override
86-
bool get isConst => element.isConst;
87+
bool get isConst => element2.isConst;
8788

88-
bool get isUnnamedConstructor => name == enclosingElement.name;
89+
bool get isUnnamedConstructor => element2.name3 == 'new';
8990

90-
bool get isFactory => element.isFactory;
91+
bool get isFactory => element2.isFactory;
9192

9293
@override
9394
Kind get kind => Kind.constructor;
9495

95-
late final Callable modelType = getTypeFor(element.type, library) as Callable;
96+
late final Callable modelType =
97+
getTypeFor(element2.type, library) as Callable;
9698

9799
@override
98-
String get name {
99-
// TODO(jcollins-g): After the old lookup code is retired, rationalize
100-
// [name] around the conventions used in referenceChildren and replace
101-
// code there and elsewhere with simple references to the name.
102-
var constructorName = element.name;
103-
if (constructorName.isEmpty) {
104-
return enclosingElement.name;
105-
}
106-
return '${enclosingElement.name}.$constructorName';
107-
}
100+
String get name =>
101+
// TODO(jcollins-g): After the old lookup code is retired, rationalize
102+
// [name] around the conventions used in referenceChildren and replace
103+
// code there and elsewhere with simple references to the name.
104+
'${enclosingElement.name}.${element2.name3}';
108105

109106
@override
110107
String get nameWithGenerics {
111-
var constructorName = element.name;
112-
if (constructorName.isEmpty) {
108+
var constructorName = element2.name3!;
109+
if (constructorName == 'new') {
113110
return '${enclosingElement.name}$genericParameters';
114111
}
115112
return '${enclosingElement.name}$genericParameters.$constructorName';
116113
}
117114

118115
String? get shortName {
119116
if (name.contains('.')) {
120-
return name.substring(element.enclosingElement3.name.length + 1);
117+
return name.substring(element2.enclosingElement2.name3!.length + 1);
121118
} else {
122119
return name;
123120
}
@@ -126,17 +123,17 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters {
126123
@override
127124
late final Map<String, CommentReferable> referenceChildren = () {
128125
// Find the element that [parameter] is _really_ referring to.
129-
Element? dereferenceParameter(ParameterElement? parameter) =>
126+
Element2? dereferenceParameter(FormalParameterElement? parameter) =>
130127
switch (parameter) {
131-
FieldFormalParameterElement() => parameter.field,
132-
SuperFormalParameterElement() =>
133-
dereferenceParameter(parameter.superConstructorParameter),
128+
FieldFormalParameterElement2() => parameter.field2,
129+
SuperFormalParameterElement2() =>
130+
dereferenceParameter(parameter.superConstructorParameter2),
134131
_ => parameter
135132
};
136133

137134
var parameterElements = parameters.map((parameter) {
138-
var element = dereferenceParameter(parameter.element);
139-
return element == null ? parameter : getModelForElement(element);
135+
var element = dereferenceParameter(parameter.element2);
136+
return element == null ? parameter : getModelForElement2(element);
140137
});
141138
return {
142139
for (var element in parameterElements) element.referenceName: element,
@@ -146,5 +143,5 @@ class Constructor extends ModelElement with ContainerMember, TypeParameters {
146143

147144
@override
148145
String get referenceName =>
149-
isUnnamedConstructor ? enclosingElement.name : element.name;
146+
isUnnamedConstructor ? enclosingElement.name : element2.name3!;
150147
}

lib/src/model/getter_setter_combo.dart

+5-3
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ mixin GetterSetterCombo on ModelElement {
8383
String linkifyConstantValue(String original) {
8484
if (_constantInitializer is! InstanceCreationExpression) return original;
8585

86-
var constructorName = _constantInitializer.constructorName.toString();
8786
var element = _constantInitializer.constructorName.element;
8887
if (element == null) return original;
8988

@@ -93,8 +92,11 @@ mixin GetterSetterCombo on ModelElement {
9392

9493
// TODO(jcollins-g): this logic really should be integrated into
9594
// `Constructor`, but that's not trivial because of `linkedName`'s usage.
96-
if (enclosingElement.name == target.name) {
97-
return original.replaceAll(constructorName, target.linkedName);
95+
if (target.isUnnamedConstructor) {
96+
var parts = target.linkedNameParts;
97+
// We don't want the `.new` representation of an unnamed constructor.
98+
var linkedName = '${parts.tag}${enclosingElement.name}${parts.endTag}';
99+
return original.replaceAll(enclosingElement.name, linkedName);
98100
}
99101
return original.replaceAll('${enclosingElement.name}.${target.name}',
100102
'${enclosingElement.linkedName}.${target.linkedName}');

lib/src/model/inheriting_container.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ mixin Constructable implements InheritingContainer {
2828

2929
@override
3030
late final List<Constructor> publicConstructorsSorted =
31-
constructors.wherePublic.toList(growable: false)..sort();
31+
constructors.wherePublic.toList(growable: false)..sort(byName);
3232

3333
@override
3434
@visibleForOverriding

lib/src/model/model_element.dart

+16-5
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ abstract class ModelElement
228228
if (e is ExecutableMember) {
229229
originalMember = e;
230230
e = e.baseElement;
231-
} else if (e is FieldMember){
231+
} else if (e is FieldMember) {
232232
originalMember = e;
233-
e = e.baseElement;
233+
e = e.baseElement;
234234
}
235235

236236
// Return the cached ModelElement if it exists.
@@ -676,7 +676,14 @@ abstract class ModelElement
676676
@override
677677
Library get library => _library;
678678

679+
/// The name of this element, wrapped in an HTML link (an `<a>` tag) if [href]
680+
/// is non-`null`.
679681
late final String linkedName = () {
682+
var parts = linkedNameParts;
683+
return '${parts.tag}${parts.text}${parts.endTag}';
684+
}();
685+
686+
({String tag, String text, String endTag}) get linkedNameParts {
680687
// If `name` is empty, we probably have the wrong Element association or
681688
// there's an analyzer issue.
682689
assert(name.isNotEmpty ||
@@ -689,12 +696,16 @@ abstract class ModelElement
689696
if (isPublicAndPackageDocumented) {
690697
warn(PackageWarning.noCanonicalFound);
691698
}
692-
return htmlEscape.convert(name);
699+
return (tag: '', text: htmlEscape.convert(name), endTag: '');
693700
}
694701

695702
var cssClass = isDeprecated ? ' class="deprecated"' : '';
696-
return '<a$cssClass href="$href">$displayName</a>';
697-
}();
703+
return (
704+
tag: '<a$cssClass href="$href">',
705+
text: displayName,
706+
endTag: '</a>'
707+
);
708+
}
698709

699710
ParameterRenderer get _parameterRenderer => const ParameterRendererHtml();
700711

lib/src/model/nameable.dart

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:analyzer/src/utilities/extensions/element.dart';
1212
import 'package:collection/collection.dart';
1313
import 'package:dartdoc/src/element_type.dart';
1414
import 'package:dartdoc/src/model/accessor.dart';
15+
import 'package:dartdoc/src/model/constructor.dart';
1516
import 'package:dartdoc/src/model/container.dart';
1617
import 'package:dartdoc/src/model/library.dart';
1718
import 'package:dartdoc/src/model/model_element.dart';
@@ -121,7 +122,7 @@ mixin Nameable {
121122
enclosingContainer: enclosingContainer,
122123
);
123124

124-
/// Returns the [ModelElement] for [element], instantiating it if needed.
125+
/// Returns the [ModelElement] for [element], instantiating it if needed.
125126
///
126127
/// A convenience method for [ModelElement.forPropertyInducingElement], see
127128
/// its documentation.
@@ -155,6 +156,12 @@ int byName(Nameable a, Nameable b) {
155156
return compareAsciiLowerCaseNatural(a.displayName, b.displayName);
156157
}
157158

159+
if (a is Constructor && b is Constructor) {
160+
var aName = a.name.replaceFirst('.new', '');
161+
var bName = b.name.replaceFirst('.new', '');
162+
return compareAsciiLowerCaseNatural(aName, bName);
163+
}
164+
158165
var stringCompare = compareAsciiLowerCaseNatural(a.name, b.name);
159166
if (stringCompare != 0) {
160167
return stringCompare;

0 commit comments

Comments
 (0)