Skip to content

Commit c4f52cf

Browse files
authored
Test records support in typedefs (#3239)
Functionality has not really changed here; we're just adding typedefs. Related to #3202, #3233
1 parent f74e129 commit c4f52cf

File tree

5 files changed

+142
-21
lines changed

5 files changed

+142
-21
lines changed

lib/src/element_type.dart

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,13 @@ abstract class ElementType extends Privacy
7272
var isGenericTypeAlias = f.alias?.element != null && f is! InterfaceType;
7373
if (f is FunctionType) {
7474
assert(f is ParameterizedType);
75-
// This is an indication we have an extremely out of date analyzer.
76-
assert(!isGenericTypeAlias, 'should never occur: out of date analyzer?');
7775
// And finally, delete this case and its associated class
7876
// after https://dart-review.googlesource.com/c/sdk/+/201520
7977
// is in all published versions of analyzer this version of dartdoc
8078
// is compatible with.
8179
return CallableElementType(f, library, packageGraph, element);
82-
} else if (isGenericTypeAlias) {
80+
}
81+
if (isGenericTypeAlias) {
8382
return GenericTypeAliasElementType(
8483
f as TypeParameterType, library, packageGraph, element);
8584
}
@@ -315,8 +314,7 @@ abstract class DefinedElementType extends ElementType {
315314
final bound = _bound;
316315
if (bound is InterfaceType &&
317316
!bound.typeArguments.every((t) => t is InterfaceType)) {
318-
var typeSystem = library.element.typeSystem;
319-
return typeSystem.instantiateInterfaceToBounds(
317+
return library.typeSystem.instantiateInterfaceToBounds(
320318
element: bound.element, nullabilitySuffix: _bound.nullabilitySuffix);
321319
} else {
322320
return _bound;

lib/src/model/inheriting_container.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -302,14 +302,14 @@ abstract class InheritingContainer extends Container
302302
var parent = supertype;
303303
while (parent != null) {
304304
typeChain.add(parent);
305-
if (parent.type is InterfaceType) {
306-
// Avoid adding [Object] to the superChain (_supertype already has this
307-
// check)
308-
if ((parent.type as InterfaceType).superclass?.superclass == null) {
309-
parent = null;
305+
final parentType = parent.type;
306+
if (parentType is InterfaceType) {
307+
// Avoid adding [Object] to the [superChain] ([_supertype] already has
308+
// this check).
309+
if (parentType.superclass?.superclass == null) {
310+
break;
310311
} else {
311-
parent = modelBuilder.typeFrom(
312-
(parent.type as InterfaceType).superclass!, library)
312+
parent = modelBuilder.typeFrom(parentType.superclass!, library)
313313
as DefinedElementType?;
314314
}
315315
} else {

lib/src/type_utils.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ extension DartTypeExtension on DartType {
1616
} else if (self is TypeParameterType) {
1717
return self.element;
1818
} else {
19-
// Remaining cases like `DynamicType`, `FunctionType`, and `VoidType`.
19+
// Remaining cases like `DynamicType`, `FunctionType`, `RecordType`, and
20+
// `VoidType`.
2021
return null;
2122
}
2223
}

test/typedef_test.dart

Lines changed: 129 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import 'src/test_descriptor_utils.dart' as d;
1111
import 'src/utils.dart';
1212

1313
void main() {
14-
group('typedefs', () {
14+
group('typedefs of function types', () {
1515
late Library library;
1616

1717
// It is expensive (~10s) to compute a package graph, even skipping
@@ -33,6 +33,7 @@ typedef Cb1 = void Function();
3333
3434
typedef Cb2<T> = T Function(T);
3535
36+
/// Not unlike [Cb2].
3637
typedef Cb3<T> = Cb2<List<T>>;
3738
'''),
3839
],
@@ -52,12 +53,12 @@ typedef Cb3<T> = Cb2<List<T>>;
5253
library = packageGraph.libraries.named(libraryName);
5354
});
5455

55-
test('basic typedef', () async {
56+
test('basic function typedef', () async {
5657
final cb1Typedef = library.typedefs.named('Cb1');
5758

5859
expect(cb1Typedef.nameWithGenerics, 'Cb1');
5960
expect(cb1Typedef.genericParameters, '');
60-
expect(cb1Typedef.aliasedType is FunctionType, isTrue);
61+
expect(cb1Typedef.aliasedType, isA<FunctionType>());
6162
expect(cb1Typedef.documentationComment, '''
6263
/// Line _one_.
6364
///
@@ -72,7 +73,7 @@ Line _two_.''');
7273
<p>Line <em>two</em>.</p>''');
7374
});
7475

75-
test('generic typedef', () async {
76+
test('generic function typedef', () async {
7677
final cb2Typedef = library.typedefs.named('Cb2');
7778

7879
expect(
@@ -83,10 +84,10 @@ Line _two_.''');
8384
cb2Typedef.genericParameters,
8485
'&lt;<wbr><span class="type-parameter">T</span>&gt;',
8586
);
86-
expect(cb2Typedef.aliasedType is FunctionType, isTrue);
87+
expect(cb2Typedef.aliasedType, isA<FunctionType>());
8788
});
8889

89-
test('generic typedef referring to a generic typedef', () async {
90+
test('generic function typedef referring to a generic typedef', () async {
9091
final cb3Typedef = library.typedefs.named('Cb3');
9192

9293
expect(
@@ -97,11 +98,132 @@ Line _two_.''');
9798
cb3Typedef.genericParameters,
9899
'&lt;<wbr><span class="type-parameter">T</span>&gt;',
99100
);
100-
expect(cb3Typedef.aliasedType is FunctionType, isTrue);
101+
expect(cb3Typedef.aliasedType, isA<FunctionType>());
101102

102103
expect(cb3Typedef.parameters, hasLength(1));
103104

104105
// TODO(srawlins): Dramatically improve typedef testing.
105106
});
107+
108+
test('typedef in a doc comment reference', () {
109+
final cb3Typedef = library.typedefs.named('Cb3');
110+
111+
expect(cb3Typedef.isDocumented, isTrue);
112+
113+
expect(cb3Typedef.documentation, 'Not unlike [Cb2].');
114+
115+
expect(
116+
cb3Typedef.documentationAsHtml,
117+
'<p>Not unlike '
118+
'<a href="%%__HTMLBASE_dartdoc_internal__%%typedefs/Cb2.html">Cb2</a>.'
119+
'</p>',
120+
);
121+
});
122+
});
123+
124+
group('typedefs of record types', skip: !recordsAllowed, () {
125+
late Library library;
126+
127+
// It is expensive (~10s) to compute a package graph, even skipping
128+
// unreachable Dart SDK libraries, so we set up this package once.
129+
setUpAll(() async {
130+
const libraryName = 'typedefs';
131+
final packageMetaProvider = testPackageMetaProvider;
132+
133+
final packagePath = await d.createPackage(
134+
libraryName,
135+
libFiles: [
136+
d.file('lib.dart', '''
137+
library $libraryName;
138+
139+
/// Line _one_.
140+
///
141+
/// Line _two_.
142+
typedef R1 = (int, String);
143+
144+
typedef R2<T> = (T, String);
145+
146+
/// Not unlike [R2].
147+
typedef R3<T> = R2<List<T>>;
148+
'''),
149+
],
150+
resourceProvider:
151+
packageMetaProvider.resourceProvider as MemoryResourceProvider,
152+
);
153+
final packageConfigProvider =
154+
getTestPackageConfigProvider(packageMetaProvider.defaultSdkDir.path);
155+
packageConfigProvider.addPackageToConfigFor(
156+
packagePath, libraryName, Uri.file('$packagePath/'));
157+
158+
final packageGraph = await bootBasicPackage(
159+
packagePath,
160+
packageMetaProvider,
161+
packageConfigProvider,
162+
);
163+
library = packageGraph.libraries.named(libraryName);
164+
});
165+
166+
test('basic record typedef', () async {
167+
final r1Typedef = library.typedefs.named('R1');
168+
169+
expect(r1Typedef.nameWithGenerics, 'R1');
170+
expect(r1Typedef.genericParameters, '');
171+
expect(r1Typedef.aliasedType, isA<RecordType>());
172+
expect(r1Typedef.documentationComment, '''
173+
/// Line _one_.
174+
///
175+
/// Line _two_.''');
176+
expect(r1Typedef.documentation, '''
177+
Line _one_.
178+
179+
Line _two_.''');
180+
expect(r1Typedef.oneLineDoc, 'Line <em>one</em>.');
181+
expect(r1Typedef.documentationAsHtml, '''
182+
<p>Line <em>one</em>.</p>
183+
<p>Line <em>two</em>.</p>''');
184+
});
185+
186+
test('generic record typedef', () async {
187+
final r2Typedef = library.typedefs.named('R2');
188+
189+
expect(
190+
r2Typedef.nameWithGenerics,
191+
'R2&lt;<wbr><span class="type-parameter">T</span>&gt;',
192+
);
193+
expect(
194+
r2Typedef.genericParameters,
195+
'&lt;<wbr><span class="type-parameter">T</span>&gt;',
196+
);
197+
expect(r2Typedef.aliasedType, isA<RecordType>());
198+
});
199+
200+
test('generic record typedef referring to a generic typedef', () async {
201+
final r3Typedef = library.typedefs.named('R3');
202+
203+
expect(
204+
r3Typedef.nameWithGenerics,
205+
'R3&lt;<wbr><span class="type-parameter">T</span>&gt;',
206+
);
207+
expect(
208+
r3Typedef.genericParameters,
209+
'&lt;<wbr><span class="type-parameter">T</span>&gt;',
210+
);
211+
expect(r3Typedef.aliasedType, isA<RecordType>());
212+
});
213+
214+
test('typedef in a doc comment reference', () {
215+
final r3Typedef = library.typedefs.named('R3');
216+
217+
expect(r3Typedef.isDocumented, isTrue);
218+
219+
expect(r3Typedef.documentation, 'Not unlike [R2].');
220+
221+
expect(
222+
r3Typedef.documentationAsHtml,
223+
'<p>Not unlike '
224+
'<a href="%%__HTMLBASE_dartdoc_internal__%%typedefs/R2.html">R2</a>.'
225+
'</p>',
226+
);
227+
});
106228
});
107229
}

tool/mustachio/codegen_runtime_renderer.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ import '${p.basename(_sourceUri.path)}';
220220
return _relevantTypeFrom(bound);
221221
}
222222
} else {
223-
// We can do nothing with function types, etc.
223+
// We can do nothing with function types, record types, etc.
224224
return null;
225225
}
226226
}

0 commit comments

Comments
 (0)