Skip to content

Commit 2ccfe3e

Browse files
authored
Fix TypeChecker.isSuperTypeOf throws on null value
fixes #229
1 parent ced93e5 commit 2ccfe3e

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

packages/custom_lint_builder/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## Unreleased patch
22

33
- Upgrade analyzer to support 6.4.0
4+
- Fix null exception when using `TypeChecker.isSuperTypeOf` (thanks to @charlescyt)
45

56
## 0.6.1 - 2024-02-14
67

packages/custom_lint_core/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## Unreleased patch
2+
3+
- Fix null exception when using `TypeChecker.isSuperTypeOf` (thanks to @charlescyt)
4+
15
## 0.6.1 - 2024-02-14
26

37
- Exported `NodeLintRegistry`

packages/custom_lint_core/lib/src/type_checker.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,11 @@ abstract class TypeChecker {
221221
///
222222
/// This only takes into account the *extends* hierarchy. If you wish
223223
/// to check mixins and interfaces, use [isAssignableFromType].
224-
bool isSuperTypeOf(DartType staticType) => isSuperOf(staticType.element!);
224+
// TODO changelog patch: Fixed a bug where isSuperTypeOf throws if the element is null (thanks to @charlescyt)
225+
bool isSuperTypeOf(DartType staticType) {
226+
final element = staticType.element;
227+
return element != null && isSuperOf(element);
228+
}
225229
}
226230

227231
// Checks a static type against another static type;

packages/custom_lint_core/test/type_checker_test.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,32 @@ void main() {
3434
);
3535
});
3636

37+
test('Can call isSuperTypeOf in DartTypes with no element', () async {
38+
final file = writeToTemporaryFile(r'''
39+
void fn((int, String) record) {
40+
final first = record.$1;
41+
}
42+
''');
43+
44+
final unit = await resolveFile2(path: file.path);
45+
unit as ResolvedUnitResult;
46+
47+
const checker = TypeChecker.fromName('record');
48+
49+
late final PropertyAccess propertyAccessNode;
50+
unit.unit.accept(
51+
_PropertyAccessVisitor((node) {
52+
propertyAccessNode = node;
53+
}),
54+
);
55+
56+
expect(propertyAccessNode.realTarget.staticType!.element, isNull);
57+
expect(
58+
checker.isExactlyType(propertyAccessNode.realTarget.staticType!),
59+
isFalse,
60+
);
61+
});
62+
3763
group('TypeChecker.fromPackage', () {
3864
test('matches a type from a package', () async {
3965
final tempDir = Directory.systemTemp.createTempSync();
@@ -109,3 +135,15 @@ class _MethodInvocationVisitor extends RecursiveAstVisitor<void> {
109135
super.visitMethodInvocation(node);
110136
}
111137
}
138+
139+
class _PropertyAccessVisitor extends RecursiveAstVisitor<void> {
140+
_PropertyAccessVisitor(this.onPropertyAccess);
141+
142+
final void Function(PropertyAccess node) onPropertyAccess;
143+
144+
@override
145+
void visitPropertyAccess(PropertyAccess node) {
146+
onPropertyAccess(node);
147+
super.visitPropertyAccess(node);
148+
}
149+
}

0 commit comments

Comments
 (0)