Skip to content

Commit 6a84448

Browse files
authored
Add TypeChecker.any (#202)
* Add annotationsOfExact. * Add type checks. * Update CHANGELOG. * Add TypeChecker.any. * CHANGELOG. * .
1 parent 56c4f1a commit 6a84448

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
* `TypeChecker#annotations...`-methods now throw a `StateError` if one or more
99
annotations on an element are not resolvable. This is usually a sign of a
1010
mispelling, missing import, or missing dependency.
11+
12+
* Added `TypeChecker.any`, which delegates to multiple other `TypeChecker`
13+
implementations when making a type check.
1114

1215
## 0.5.10+1
1316

lib/src/type_checker.dart

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,20 @@ import 'utils.dart';
1414
abstract class TypeChecker {
1515
const TypeChecker._();
1616

17+
/// Creates a new [TypeChecker] that delegates to other [checkers].
18+
///
19+
/// This implementation will return `true` for type checks if _any_ of the
20+
/// provided type checkers return true, which is useful for deprecating an
21+
/// API:
22+
/// ```dart
23+
/// const $Foo = const TypeChecker.fromRuntime(Foo);
24+
/// const $Bar = const TypeChecker.fromRuntime(Bar);
25+
///
26+
/// // Used until $Foo is deleted.
27+
/// const $FooOrBar = const TypeChecker.forAny(const [$Foo, $Bar]);
28+
/// ```
29+
const factory TypeChecker.any(Iterable<TypeChecker> checkers) = _AnyChecker;
30+
1731
/// Create a new [TypeChecker] backed by a runtime [type].
1832
///
1933
/// This implementation uses `dart:mirrors` (runtime reflection).
@@ -71,14 +85,13 @@ abstract class TypeChecker {
7185
/// Returns annotating constants on [element] assignable to this type.
7286
Iterable<DartObject> annotationsOf(Element element) => element.metadata
7387
.map(_checkedConstantValue)
74-
.where((a) => isAssignableFromType(a.type));
88+
.where((a) => a?.type != null && isAssignableFromType(a.type));
7589

7690
/// Returns annotating constants on [element] of exactly this type.
7791
Iterable<DartObject> annotationsOfExact(Element element) => element.metadata
7892
.map(_checkedConstantValue)
79-
.where((a) => a?.type != null && isAssignableFromType(a.type));
93+
.where((a) => a?.type != null && isExactlyType(a.type));
8094

81-
/// Returns `true` if the type of [element] can be assigned to this type.
8295
/// Returns `true` if the type of [element] can be assigned to this type.
8396
bool isAssignableFrom(Element element) =>
8497
isExactly(element) || _getAllSupertypes(element).any(isExactlyType);
@@ -210,3 +223,12 @@ class _UriTypeChecker extends TypeChecker {
210223
@override
211224
String toString() => '${uri}';
212225
}
226+
227+
class _AnyChecker extends TypeChecker {
228+
final Iterable<TypeChecker> _checkers;
229+
230+
const _AnyChecker(this._checkers) : super._();
231+
232+
@override
233+
bool isExactly(Element element) => _checkers.any((c) => c.isExactly(element));
234+
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: source_gen
2-
version: 0.6.0-dev
2+
version: 0.6.0
33
author: Dart Team <[email protected]>
44
description: Automated source code generation for Dart.
55
homepage: https://github.com/dart-lang/source_gen

test/type_checker_test.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ void main() {
180180
'package:source_gen/src/generator_for_annotation.dart#GeneratorForAnnotation'));
181181
});
182182

183-
test('should gracefully when something is not resolvable', () async {
183+
test('should fail gracefully when something is not resolvable', () async {
184184
final resolver = await resolveSource(r'''
185185
library _test;
186186
@@ -194,4 +194,12 @@ void main() {
194194
expect(() => $deprecated.annotationsOf(classX), throwsStateError,
195195
reason: 'deprecated was spelled wrong; no annotation can be resolved');
196196
});
197+
198+
test('should check multiple checkers', () {
199+
final listOrMap = const TypeChecker.any(const [
200+
const TypeChecker.fromRuntime(List),
201+
const TypeChecker.fromRuntime(Map),
202+
]);
203+
expect(listOrMap.isExactlyType(staticMap), isTrue);
204+
});
197205
}

0 commit comments

Comments
 (0)