Skip to content

Commit 93b006d

Browse files
authored
Added isAssignableFrom(Type) to TypeChecker (#164)
* Added `isAssignableFrom(Type)` to TypeChecker * migrate JSON classes to new TypeChecker methods
1 parent 765c068 commit 93b006d

File tree

4 files changed

+33
-16
lines changed

4 files changed

+33
-16
lines changed

lib/generators/json_serializable_generator.dart

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class JsonSerializableGenerator
204204
}
205205
}
206206

207-
if (_implementsDartList(fieldType)) {
207+
if (_coreListChecker.isAssignableFromType(fieldType)) {
208208
var indexVal = "i${depth}";
209209

210210
var substitute = '${expression}[$indexVal]';
@@ -247,7 +247,7 @@ class JsonSerializableGenerator
247247
}
248248
}
249249

250-
if (_isDartIterable(searchType) || _isDartList(searchType)) {
250+
if (_coreIterableChecker.isAssignableFromType(searchType)) {
251251
var iterableGenericType =
252252
_getIterableGenericType(searchType as InterfaceType);
253253

@@ -257,7 +257,7 @@ class JsonSerializableGenerator
257257
"${_writeAccessToVar(itemVal, iterableGenericType, depth: depth+1)}"
258258
")";
259259

260-
if (_isDartList(searchType)) {
260+
if (_coreListChecker.isAssignableFromType(searchType)) {
261261
output += "?.toList()";
262262
}
263263

@@ -287,24 +287,24 @@ String _fieldToJsonMapKey(String fieldName, FieldElement field) {
287287
}
288288

289289
DartType _getIterableGenericType(InterfaceType type) {
290-
var iterableThing = _typeTest(type, _isDartIterable) as InterfaceType;
290+
var iterableImplementation =
291+
_getImplementationType(type, _coreIterableChecker) as InterfaceType;
291292

292-
return iterableThing.typeArguments.single;
293+
return iterableImplementation.typeArguments.single;
293294
}
294295

295-
bool _implementsDartList(DartType type) => _typeTest(type, _isDartList) != null;
296-
297-
DartType _typeTest(DartType type, bool tester(DartType type)) {
298-
if (tester(type)) return type;
296+
DartType _getImplementationType(DartType type, TypeChecker checker) {
297+
if (checker.isExactlyType(type)) return type;
299298

300299
if (type is InterfaceType) {
301-
var tests = type.interfaces.map((type) => _typeTest(type, tester));
300+
var tests =
301+
type.interfaces.map((type) => _getImplementationType(type, checker));
302302
var match = _firstNotNull(tests);
303303

304304
if (match != null) return match;
305305

306306
if (type.superclass != null) {
307-
return _typeTest(type.superclass, tester);
307+
return _getImplementationType(type.superclass, checker);
308308
}
309309
}
310310
return null;
@@ -313,8 +313,6 @@ DartType _typeTest(DartType type, bool tester(DartType type)) {
313313
T _firstNotNull<T>(Iterable<T> values) =>
314314
values.firstWhere((value) => value != null, orElse: () => null);
315315

316-
bool _isDartIterable(DartType type) =>
317-
const TypeChecker.fromUrl('dart:core#Iterable').isExactlyType(type);
316+
final _coreIterableChecker = const TypeChecker.fromUrl('dart:core#Iterable');
318317

319-
bool _isDartList(DartType type) =>
320-
const TypeChecker.fromUrl('dart:core#List').isExactlyType(type);
318+
final _coreListChecker = const TypeChecker.fromUrl('dart:core#List');

lib/src/json_serializable/type_helper.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'package:analyzer/dart/element/element.dart';
66
import 'package:analyzer/dart/element/type.dart';
7+
import 'package:source_gen/src/type_checker.dart';
78

89
abstract class TypeHelper {
910
const TypeHelper();
@@ -104,7 +105,7 @@ class DateTimeHelper extends TypeHelper {
104105
bool canDeserialize(DartType type) => _matchesType(type);
105106

106107
bool _matchesType(DartType type) =>
107-
type.element.library?.isDartCore == true && type.name == 'DateTime';
108+
const TypeChecker.fromUrl('dart:core#DateTime').isExactlyType(type);
108109

109110
@override
110111
String serialize(DartType targetType, String name) =>

lib/src/type_checker.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ abstract class TypeChecker {
4646
.map((a) => a.computeConstantValue())
4747
.where((a) => isExactlyType(a.type));
4848

49+
/// Returns `true` if representing the exact same class an or a superclass of
50+
/// [element]
51+
bool isAssignableFrom(Element element) =>
52+
isExactly(element) || isSuperOf(element);
53+
54+
/// Returns `true` if representing the exact same type as or a supertype of
55+
/// [staticType].
56+
bool isAssignableFromType(DartType staticType) =>
57+
isAssignableFrom(staticType.element);
58+
4959
/// Returns `true` if representing the exact same class as [element].
5060
bool isExactly(Element element);
5161

test/type_checker_test.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ void main() {
5252
test('should be a super type of dart:collection#HashMap', () {
5353
expect(checkMap().isSuperTypeOf(staticHashMap), isTrue);
5454
});
55+
56+
test('should be assignable from dart:collection#HashMap', () {
57+
expect(checkMap().isAssignableFromType(staticHashMap), isTrue);
58+
});
5559
});
5660

5761
group('(HashMap)', () {
@@ -63,6 +67,10 @@ void main() {
6367
test('should not be a super type of dart:core#Map', () {
6468
expect(checkHashMap().isSuperTypeOf(staticMap), isFalse);
6569
});
70+
71+
test('should not assignable from type dart:core#Map', () {
72+
expect(checkHashMap().isAssignableFromType(staticMap), isFalse);
73+
});
6674
});
6775
}
6876

0 commit comments

Comments
 (0)