router_generator.dart 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import 'package:analyzer/dart/element/element.dart';
  2. import 'package:build/build.dart';
  3. import 'package:router_gen/annotation/router_page.dart';
  4. import 'package:router_gen/annotation/router_param.dart';
  5. import 'package:router_gen/model/router.dart';
  6. import 'package:router_gen/util/utils.dart';
  7. import 'package:source_gen/source_gen.dart';
  8. import 'package:path/path.dart' as Path;
  9. /// save router annotation
  10. class RouterGenerator extends GeneratorForAnnotation<RouterPage> {
  11. final _paramChecker = const TypeChecker.fromRuntime(RouterParam);
  12. @override
  13. generateForAnnotatedElement(
  14. Element element, ConstantReader annotation, BuildStep buildStep) async {
  15. if (element.kind == ElementKind.CLASS) {
  16. router.imports.add(getImportStr(buildStep));
  17. String path = buildStep.inputId.path; // lib/xxx.dart
  18. String basename = Path.basename(buildStep.inputId.path); // xxx.dart
  19. // router name
  20. String className = element.name;
  21. String aptPath = annotation.peek("path")?.stringValue;
  22. String routerName =
  23. toCamelCase(aptPath == null || aptPath.isEmpty ? className : aptPath);
  24. var page = Page();
  25. page.name = className;
  26. page.path = routerName.startsWith("/")
  27. ? routerName
  28. : Path.join(path.replaceFirst("lib", "").replaceFirst(basename, ""),
  29. routerName);
  30. page.arguments = [];
  31. for (FieldElement e in (element as ClassElement).fields) {
  32. if (_paramChecker.hasAnnotationOf(e)) {
  33. String type = e.type.getDisplayString(withNullability: false);
  34. try {
  35. Set<String> types = getType(type);
  36. for (String importType in types) {
  37. // not container all type
  38. if (isSpeciousType(importType) == false) {
  39. continue;
  40. }
  41. print("specious type ${importType}");
  42. // 添加到imports
  43. for (LibraryElement element
  44. in (await buildStep.inputLibrary).importedLibraries) {
  45. Uri importUri = element.getType(importType)?.source?.uri;
  46. if (importUri != null) {
  47. router.imports.add(importUri.toString());
  48. } else {
  49. // 查找exports
  50. Set<LibraryElement> exports = allExportedElements(element);
  51. bool exported = false;
  52. for (LibraryElement exportElement in exports) {
  53. print("export element ${exportElement.source?.uri}");
  54. if (exportElement.getType(importType) != null) {
  55. exported = true;
  56. break;
  57. }
  58. }
  59. if (exported) {
  60. router.imports.add(element.source?.uri?.toString());
  61. }
  62. }
  63. }
  64. }
  65. } catch (e) {
  66. print(e);
  67. }
  68. bool required =
  69. e.computeConstantValue()?.getField("required")?.toBoolValue();
  70. page.arguments.add(Argument(
  71. e.name,
  72. type,
  73. required ?? true,
  74. ));
  75. }
  76. }
  77. router.routerMap[Path.basename(routerName)] = page;
  78. }
  79. return null;
  80. }
  81. Set<LibraryElement> allExportedElements(LibraryElement element) {
  82. Set<LibraryElement> allElements = Set();
  83. if (element.exports.isEmpty) {
  84. return Set()..add(element);
  85. }
  86. allElements.addAll(element.exportedLibraries);
  87. // 查找exports
  88. for (LibraryElement exportElement in element.exportedLibraries) {
  89. allElements.addAll(allExportedElements(exportElement));
  90. }
  91. return allElements;
  92. }
  93. }