Skip to content

Commit 696d570

Browse files
authored
Add typeNameOf(DartType). (#295)
* Add typeNameOf(DartType). * Dartfmt.
1 parent feff6aa commit 696d570

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## 0.7.4-dev
22

3+
* Added `typeNameOf`, which is a safe way to get the name of a `DartType`,
4+
even when the type is a `FunctionType`, which has a `null` name in newer
5+
versions of the Dart analyzer.
6+
37
* Added `LibraryReader.pathToUrl(Uri|String)`, which computes the `import` or
48
`export` path necessary to reach the provided URL from the current library.
59
Also added `pathToAsset` and `pathToElement` as convenience functions.

lib/source_gen.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export 'src/generator_for_annotation.dart';
1212
export 'src/library.dart' show AnnotatedElement, LibraryReader;
1313
export 'src/span_for_element.dart' show spanForElement;
1414
export 'src/type_checker.dart' show TypeChecker;
15+
export 'src/utils.dart' show typeNameOf;

lib/src/utils.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analyzer/dart/element/element.dart';
6+
import 'package:analyzer/dart/element/type.dart';
67
import 'package:build/build.dart';
78
import 'package:path/path.dart' as p;
89

@@ -39,6 +40,26 @@ String friendlyNameForElement(Element element) {
3940
return names.join(' ');
4041
}
4142

43+
/// Returns a non-null name for the provided [type].
44+
///
45+
/// In newer versions of the Dart analyzer, a `typedef` does not keep the
46+
/// existing `name`, because it is used an alias:
47+
/// ```
48+
/// // Used to return `VoidFunc` for name, is now `null`.
49+
/// typedef VoidFunc = void Function();
50+
/// ```
51+
///
52+
/// This function will return `'VoidFunc'`, unlike [DartType.name].
53+
String typeNameOf(DartType type) {
54+
if (type is FunctionType) {
55+
final element = type.element;
56+
if (element is GenericFunctionTypeElement) {
57+
return element.enclosingElement.name;
58+
}
59+
}
60+
return type.name;
61+
}
62+
4263
/// Returns a name suitable for `part of "..."` when pointing to [element].
4364
///
4465
/// Returns `null` if [element] is missing identifier.

test/utils_test.dart

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// Increase timeouts on this test which resolves source code and can be slow.
6+
@Timeout.factor(2.0)
7+
import 'package:analyzer/dart/element/element.dart';
8+
import 'package:build_test/build_test.dart';
9+
import 'package:source_gen/source_gen.dart';
10+
import 'package:test/test.dart';
11+
12+
void main() {
13+
ClassElement example;
14+
15+
setUpAll(() async {
16+
const source = r'''
17+
library example;
18+
19+
abstract class Example {
20+
ClassType classType();
21+
FunctionType functionType();
22+
}
23+
24+
class ClassType {}
25+
typedef FunctionType();
26+
''';
27+
example = await resolveSource(
28+
source,
29+
(resolver) => resolver
30+
.findLibraryByName('example')
31+
.then((e) => e.getType('Example')));
32+
});
33+
34+
test('should return the name of a class type', () {
35+
final classType = example.methods.first.returnType;
36+
expect(typeNameOf(classType), 'ClassType');
37+
});
38+
39+
test('should return the name of a function type', () {
40+
final functionType = example.methods.last.returnType;
41+
expect(typeNameOf(functionType), 'FunctionType');
42+
});
43+
}

0 commit comments

Comments
 (0)