Skip to content

Commit 56c4f1a

Browse files
authored
Nicer failures when an annotation is not resolvable (#201)
* Add annotationsOfExact. * Add type checks. * Update CHANGELOG.
1 parent 0593ca3 commit 56c4f1a

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
result we've added `#annotationsOfExact|firstAnnotationOfExact` which has the
66
old behavior for precise checks.
77

8+
* `TypeChecker#annotations...`-methods now throw a `StateError` if one or more
9+
annotations on an element are not resolvable. This is usually a sign of a
10+
mispelling, missing import, or missing dependency.
11+
812
## 0.5.10+1
913

1014
* Update minimum `analyzer` package to `0.29.10`.

lib/src/type_checker.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,27 @@ abstract class TypeChecker {
5858
return results.isEmpty ? null : results.first;
5959
}
6060

61+
DartObject _checkedConstantValue(ElementAnnotation annotation) {
62+
final result = annotation.computeConstantValue();
63+
if (result == null) {
64+
throw new StateError(
65+
'Could not resolve $annotation. An import or dependency may be '
66+
'missing or invalid.');
67+
}
68+
return result;
69+
}
70+
6171
/// Returns annotating constants on [element] assignable to this type.
6272
Iterable<DartObject> annotationsOf(Element element) => element.metadata
63-
.map((a) => a.computeConstantValue())
73+
.map(_checkedConstantValue)
6474
.where((a) => isAssignableFromType(a.type));
6575

6676
/// Returns annotating constants on [element] of exactly this type.
6777
Iterable<DartObject> annotationsOfExact(Element element) => element.metadata
68-
.map((a) => a.computeConstantValue())
69-
.where((a) => isExactlyType(a.type));
78+
.map(_checkedConstantValue)
79+
.where((a) => a?.type != null && isAssignableFromType(a.type));
7080

81+
/// Returns `true` if the type of [element] can be assigned to this type.
7182
/// Returns `true` if the type of [element] can be assigned to this type.
7283
bool isAssignableFrom(Element element) =>
7384
isExactly(element) || _getAllSupertypes(element).any(isExactlyType);

test/type_checker_test.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,19 @@ void main() {
179179
checkGeneratorForAnnotation: () => const TypeChecker.fromUrl(
180180
'package:source_gen/src/generator_for_annotation.dart#GeneratorForAnnotation'));
181181
});
182+
183+
test('should gracefully when something is not resolvable', () async {
184+
final resolver = await resolveSource(r'''
185+
library _test;
186+
187+
@depracated // Intentionally mispelled.
188+
class X {}
189+
''');
190+
final lib = resolver.getLibraryByName('_test');
191+
final classX = lib.getType('X');
192+
final $deprecated = const TypeChecker.fromRuntime(Deprecated);
193+
194+
expect(() => $deprecated.annotationsOf(classX), throwsStateError,
195+
reason: 'deprecated was spelled wrong; no annotation can be resolved');
196+
});
182197
}

0 commit comments

Comments
 (0)