Skip to content

Commit f1bd468

Browse files
dickermoshesrawlins
authored andcommitted
parse records and typedef in type arguments
1 parent df36812 commit f1bd468

File tree

3 files changed

+94
-12
lines changed

3 files changed

+94
-12
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
* Require dart_style >= 2.3.7, so that the current Dart language version can be
1010
passed to `DartFormatter`.
1111
* Add topics to `pubspec.yaml`.
12+
* Fix a bug where typedef-aliases in type arguments were not correctly
13+
resolved.
14+
* Fix a bug where record types were not correctly resolved.
1215

1316
## 5.4.4
1417

lib/src/builder.dart

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -167,25 +167,28 @@ $rawOutput
167167
// `Future`, which is needed when overriding some methods which return
168168
// `FutureOr`.
169169
final typeVisitor = _TypeVisitor(entryLib.typeProvider.futureDynamicType);
170-
final seenTypes = <analyzer.InterfaceType>{};
170+
final seenTypes = <analyzer.DartType>{};
171171
final librariesWithTypes = <LibraryElement>{};
172172

173-
void addTypesFrom(analyzer.InterfaceType type) {
173+
void addTypesFrom(analyzer.DartType type) {
174174
// Prevent infinite recursion.
175175
if (seenTypes.contains(type)) {
176176
return;
177177
}
178178
seenTypes.add(type);
179-
librariesWithTypes.add(type.element.library);
180-
type.element.accept(typeVisitor);
181-
if (type.alias != null) type.alias!.element.accept(typeVisitor);
182-
// For a type like `Foo<Bar>`, add the `Bar`.
183-
type.typeArguments
184-
.whereType<analyzer.InterfaceType>()
185-
.forEach(addTypesFrom);
186-
// For a type like `Foo extends Bar<Baz>`, add the `Baz`.
187-
for (final supertype in type.allSupertypes) {
188-
addTypesFrom(supertype);
179+
librariesWithTypes.addAll([
180+
if (type.element?.library != null) type.element!.library!,
181+
if (type.alias?.element.library != null) type.alias!.element.library,
182+
]);
183+
type.element?.accept(typeVisitor);
184+
type.alias?.element.accept(typeVisitor);
185+
switch (type) {
186+
case analyzer.InterfaceType interface:
187+
interface.typeArguments.forEach(addTypesFrom);
188+
interface.allSupertypes.forEach(addTypesFrom);
189+
case analyzer.RecordType record:
190+
record.positionalTypes.forEach(addTypesFrom);
191+
record.namedTypes.map((e) => e.type).forEach(addTypesFrom);
189192
}
190193
}
191194

test/builder/auto_mocks_test.dart

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3582,6 +3582,34 @@ void main() {
35823582
expect(mocksContent, contains('class MockBaz extends _i1.Mock'));
35833583
expect(mocksContent, contains('implements _i2.Baz'));
35843584
});
3585+
3586+
test('when a type parameter is a typedef a function', () async {
3587+
final mocksContent = await buildWithNonNullable({
3588+
...annotationsAsset,
3589+
'foo|lib/foo.dart': dedent(r'''
3590+
typedef CreateInt = int Function();
3591+
3592+
class BaseFoo<T> {
3593+
BaseFoo(this.t);
3594+
final T t;
3595+
}
3596+
3597+
class Foo extends BaseFoo<CreateInt> {
3598+
Foo() : super(() => 1);
3599+
}
3600+
'''),
3601+
'foo|test/foo_test.dart': '''
3602+
import 'package:foo/foo.dart';
3603+
import 'package:mockito/annotations.dart';
3604+
3605+
@GenerateMocks([Foo])
3606+
void main() {}
3607+
'''
3608+
});
3609+
3610+
expect(mocksContent, contains('class MockFoo extends _i1.Mock'));
3611+
expect(mocksContent, contains('implements _i2.Foo'));
3612+
});
35853613
});
35863614

35873615
test('generation throws when the aliased type is nullable', () {
@@ -3649,6 +3677,54 @@ void main() {
36493677
contains('returnValue: _i3.Future<(int, {_i2.Bar bar})>.value('),
36503678
contains('bar: _FakeBar_0('))));
36513679
});
3680+
test('are supported as typedefs', () async {
3681+
final mocksContent = await buildWithNonNullable({
3682+
...annotationsAsset,
3683+
'foo|lib/foo.dart': dedent(r'''
3684+
class Bar {}
3685+
class BaseFoo<T> {
3686+
BaseFoo(this.t);
3687+
final T t;
3688+
}
3689+
class Foo extends BaseFoo<(Bar, Bar)> {
3690+
Foo() : super((Bar(), Bar()));
3691+
}
3692+
'''),
3693+
'foo|test/foo_test.dart': '''
3694+
import 'package:foo/foo.dart';
3695+
import 'package:mockito/annotations.dart';
3696+
@GenerateMocks([Foo])
3697+
void main() {}
3698+
'''
3699+
});
3700+
3701+
expect(mocksContent, contains('class MockFoo extends _i1.Mock'));
3702+
expect(mocksContent, contains('implements _i2.Foo'));
3703+
});
3704+
test('are supported as nested typedefs', () async {
3705+
final mocksContent = await buildWithNonNullable({
3706+
...annotationsAsset,
3707+
'foo|lib/foo.dart': dedent(r'''
3708+
class Bar {}
3709+
class BaseFoo<T> {
3710+
BaseFoo(this.t);
3711+
final T t;
3712+
}
3713+
class Foo extends BaseFoo<(int, (Bar, Bar))> {
3714+
Foo() : super(((1, (Bar(), Bar()))));
3715+
}
3716+
'''),
3717+
'foo|test/foo_test.dart': '''
3718+
import 'package:foo/foo.dart';
3719+
import 'package:mockito/annotations.dart';
3720+
@GenerateMocks([Foo])
3721+
void main() {}
3722+
'''
3723+
});
3724+
3725+
expect(mocksContent, contains('class MockFoo extends _i1.Mock'));
3726+
expect(mocksContent, contains('implements _i2.Foo'));
3727+
});
36523728
});
36533729

36543730
group('Extension types', () {

0 commit comments

Comments
 (0)