├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.yaml ├── lib ├── builder.dart ├── example │ ├── page_a.dart │ ├── page_b.dart │ ├── page_c.dart │ ├── page_d.dart │ ├── router.route.dart │ └── router.route.internal.dart ├── route.dart └── src │ ├── collector.dart │ ├── page_config_map_util.dart │ ├── route_generator.dart │ ├── tpl.dart │ └── writer.dart ├── pubspec.lock └── pubspec.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .dart_tool 2 | .packages -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.1 2 | 3 | - Ready for experimentation. 4 | 5 | ## 0.0.1+1 6 | 7 | - Format code by lint rules. 8 | 9 | ## 0.0.2 10 | 11 | - Remove dependency to \$RouteOption. 12 | - Name Change: replace \$ to 'A' for prefix 13 | - Make abstract class to expouse the usable API 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 alibaba-flutter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # annotation_route 2 | 3 | # Description 4 | 5 | a router config mapping solution based on source_gen through annotation 6 | 7 | # Usage 8 | 9 | 1. **Notice:** your page should own a constuctor that can be initialized with unique param, then Annotate the page class with @ARoute 10 | example: 11 | 12 | ```Dart 13 | @ARoute(url: 'myapp://pagea') 14 | class A { 15 | A(MyRouteOption option): super(); 16 | } 17 | ``` 18 | 19 | 2. Annotate **your own router class** with **@ARouteRoot** 20 | example: 21 | 22 | ```Dart 23 | @ARouteRoot() 24 | class MyRouter {} 25 | ``` 26 | 27 | 3. run the build_annotation_route.sh in your workspace Or just run the command below in your workspace 28 | build: 29 | 30 | ```shell 31 | flutter packages pub run build_runner build --delete-conflicting-outputs 32 | ``` 33 | 34 | suggest you running the clean command before build: 35 | clean: 36 | 37 | ```shell 38 | flutter packages pub run build_runner clean 39 | ``` 40 | 41 | 4. now you can get the instance 42 | example: 43 | 44 | ```Dart 45 | @ARouteRoot() 46 | class Router { 47 | ARouterInternal internal = ARouterInternalImpl(); 48 | dynamic getPage(MyRouteOption option) { 49 | return internal.findPage( 50 | ARouteOption(option.urlpattern, option.params), option); 51 | } 52 | } 53 | 54 | class MyRouteOption { 55 | String urlpattern; 56 | Map params; 57 | } 58 | ``` 59 | 60 | 5. examples placed in 'lib/example/\*' 61 | 62 | # Installation 63 | 64 | ## install from packages 65 | 66 | add packages to dev_dependencies in your pubspec.yaml 67 | example: 68 | 69 | ```yaml 70 | dev_dependencies: 71 | annotation_route: any 72 | ``` 73 | 74 | ## install from source code 75 | 76 | clone the code, then put it into your workspace, announce it in your pubspec.yaml 77 | exxample: 78 | 79 | ```yaml 80 | dev_dependencies: 81 | annotation_route: 82 | path: annotation_route 83 | ``` 84 | 85 | --- 86 | 87 | # 简介 88 | 89 | 一个以注解方式实现的路由映射解决方案,基于 source_gen 90 | 91 | # 使用 92 | 93 | 1. **注意**: 你的页面应该实现指定的构造器,一个接受唯一参数的构造器,然后使用@ARoute 注解你的页面类 94 | 例: 95 | 96 | ```Dart 97 | @ARoute(url: 'myapp://pagea') 98 | class A { 99 | A(MyRouteOption option): super(); 100 | } 101 | ``` 102 | 103 | 2. 使用 **@ARouteRoot** 注解 **你自己**的 router 类 104 | 例: 105 | 106 | ```Dart 107 | @ARouteRoot() 108 | class MyRouter {} 109 | ``` 110 | 111 | 3. 在你的工作目录下运行 build_annotation_route.sh 脚本,或者运行如下命令: 112 | build: 113 | 114 | ```shell 115 | flutter packages pub run build_runner build --delete-conflicting-outputs 116 | ``` 117 | 118 | 建议在执行 build 命令前,先执行如下命令: 119 | clean: 120 | 121 | ```shell 122 | flutter packages pub run build_runner clean 123 | ``` 124 | 125 | 4. 现在你可以使用它来获取类的实例了 126 | 例: 127 | 128 | ```Dart 129 | @ARouteRoot() 130 | class Router { 131 | ARouterInternal internal = ARouterInternalImpl(); 132 | dynamic getPage(MyRouteOption option) { 133 | return internal.findPage( 134 | ARouteOption(option.urlpattern, option.params), option); 135 | } 136 | } 137 | 138 | class MyRouteOption { 139 | String urlpattern; 140 | Map params; 141 | } 142 | ``` 143 | 144 | 5. 具体代码可以参考 lib/example/\*下的文件 145 | 146 | # 安装 147 | 148 | ## 从 pub 安装 149 | 150 | 在你的 pubspec.yaml 文件下声明 151 | 例: 152 | 153 | ```yaml 154 | dev_dependencies: 155 | annotation_route: any 156 | ``` 157 | 158 | ## 从源码安装 159 | 160 | 拷贝代码至你的工作目录,在你的 pubspec.yaml 文件下声明 161 | 例: 162 | 163 | ```yaml 164 | dev_dependencies: 165 | annotation_route: 166 | path: annotation_route 167 | ``` 168 | -------------------------------------------------------------------------------- /build.yaml: -------------------------------------------------------------------------------- 1 | # Read about `build.yaml` at https://pub.dartlang.org/packages/build_config 2 | targets: 3 | $default: 4 | builders: 5 | annotation_route|route_builder: 6 | enabled: true 7 | generate_for: 8 | exclude: ['**.internal.dart'] 9 | annotation_route|route_write_builder: 10 | enabled: true 11 | options: { 'write': true } 12 | generate_for: 13 | exclude: ['**.internal.dart'] 14 | 15 | builders: 16 | route_write_builder: 17 | import: 'package:annotation_route/builder.dart' 18 | builder_factories: ['routeWriteBuilder'] 19 | build_extensions: { '.route.dart': ['.internal.dart'] } 20 | auto_apply: root_package 21 | build_to: source 22 | 23 | route_builder: 24 | import: 'package:annotation_route/builder.dart' 25 | builder_factories: ['routeBuilder'] 26 | build_extensions: { '.dart': ['.internal_invalid.dart'] } 27 | auto_apply: root_package 28 | runs_before: ['annotation_route|route_write_builder'] 29 | build_to: source 30 | -------------------------------------------------------------------------------- /lib/builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:source_gen/source_gen.dart'; 2 | import 'package:build/build.dart'; 3 | 4 | import 'src/route_generator.dart'; 5 | 6 | Builder routeBuilder(BuilderOptions options) => LibraryBuilder(RouteGenerator(), 7 | generatedExtension: '.internal_invalid.dart'); 8 | 9 | Builder routeWriteBuilder(BuilderOptions options) => 10 | LibraryBuilder(RouteWriterGenerator(), 11 | generatedExtension: '.internal.dart'); 12 | -------------------------------------------------------------------------------- /lib/example/page_a.dart: -------------------------------------------------------------------------------- 1 | import 'package:annotation_route/route.dart'; 2 | 3 | @ARoute(url: 'myapp://pagea') 4 | class A { 5 | int a; 6 | String b; 7 | A(ARouteOption option) : super(); 8 | } 9 | -------------------------------------------------------------------------------- /lib/example/page_b.dart: -------------------------------------------------------------------------------- 1 | import 'package:annotation_route/route.dart'; 2 | 3 | @ARoute(url: 'myapp://pageb', params: {'parama': 'b'}) 4 | class B { 5 | int a; 6 | String b; 7 | B(ARouteOption option) : super(); 8 | } 9 | -------------------------------------------------------------------------------- /lib/example/page_c.dart: -------------------------------------------------------------------------------- 1 | import 'package:annotation_route/route.dart'; 2 | 3 | @ARoute(alias: [ 4 | ARouteAlias(url: 'myapp://pagec'), 5 | ARouteAlias(url: 'myapp://pagec_alias') 6 | ]) 7 | class C { 8 | int a; 9 | String b; 10 | C(ARouteOption option) : super(); 11 | } 12 | -------------------------------------------------------------------------------- /lib/example/page_d.dart: -------------------------------------------------------------------------------- 1 | import 'package:annotation_route/route.dart'; 2 | 3 | @ARoute(alias: [ 4 | ARouteAlias(url: 'myapp://paged', params: {'parama': 'd'}) 5 | ]) 6 | class D { 7 | int a; 8 | String b; 9 | D(ARouteOption option) : super(); 10 | } 11 | -------------------------------------------------------------------------------- /lib/example/router.route.dart: -------------------------------------------------------------------------------- 1 | import 'package:annotation_route/route.dart'; 2 | import 'router.route.internal.dart'; 3 | 4 | @ARouteRoot() 5 | class Router { 6 | ARouterInternal internal = ARouterInternalImpl(); 7 | dynamic getPage(MyRouteOption option) { 8 | return internal.findPage( 9 | ARouteOption(option.urlpattern, option.params), option); 10 | } 11 | } 12 | 13 | class MyRouteOption { 14 | String urlpattern; 15 | Map params; 16 | } 17 | -------------------------------------------------------------------------------- /lib/example/router.route.internal.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | // ************************************************************************** 4 | // RouteWriterGenerator 5 | // ************************************************************************** 6 | 7 | import 'dart:convert'; 8 | import 'package:annotation_route/route.dart'; 9 | import 'package:annotation_route/example/page_a.dart'; 10 | import 'package:annotation_route/example/page_d.dart'; 11 | import 'package:annotation_route/example/page_b.dart'; 12 | import 'package:annotation_route/example/page_c.dart'; 13 | 14 | abstract class ARouterInternal { 15 | bool hasPageConfig(ARouteOption option); 16 | ARouterResult findPage(ARouteOption option, dynamic initOption); 17 | } 18 | 19 | class ARouterInternalImpl extends ARouterInternal { 20 | ARouterInternalImpl(); 21 | final Map>> innerRouterMap = 22 | >>{ 23 | 'myapp://pagea': [ 24 | {'clazz': A} 25 | ], 26 | 'myapp://paged': [ 27 | {'clazz': D, 'params': '{"parama":"d"}'} 28 | ], 29 | 'myapp://pageb': [ 30 | {'clazz': B, 'params': '{"parama":"b"}'} 31 | ], 32 | 'myapp://pagec': [ 33 | {'clazz': C} 34 | ], 35 | 'myapp://pagec_alias': [ 36 | {'clazz': C} 37 | ] 38 | }; 39 | 40 | @override 41 | bool hasPageConfig(ARouteOption option) { 42 | final dynamic pageConfig = findPageConfig(option); 43 | return pageConfig != null; 44 | } 45 | 46 | @override 47 | ARouterResult findPage(ARouteOption option, dynamic initOption) { 48 | final dynamic pageConfig = findPageConfig(option); 49 | if (pageConfig != null) { 50 | return implFromPageConfig(pageConfig, initOption); 51 | } else { 52 | return ARouterResult(state: ARouterResultState.NOT_FOUND); 53 | } 54 | } 55 | 56 | void instanceCreated( 57 | dynamic clazzInstance, Map pageConfig) {} 58 | 59 | dynamic instanceFromClazz(Type clazz, dynamic option) { 60 | switch (clazz) { 61 | case A: 62 | return new A(option); 63 | case D: 64 | return new D(option); 65 | case B: 66 | return new B(option); 67 | case C: 68 | return new C(option); 69 | default: 70 | return null; 71 | } 72 | } 73 | 74 | ARouterResult implFromPageConfig( 75 | Map pageConfig, dynamic option) { 76 | final String interceptor = pageConfig['interceptor']; 77 | if (interceptor != null) { 78 | return ARouterResult( 79 | state: ARouterResultState.REDIRECT, interceptor: interceptor); 80 | } 81 | final Type clazz = pageConfig['clazz']; 82 | if (clazz == null) { 83 | return ARouterResult(state: ARouterResultState.NOT_FOUND); 84 | } 85 | try { 86 | final dynamic clazzInstance = instanceFromClazz(clazz, option); 87 | instanceCreated(clazzInstance, pageConfig); 88 | return ARouterResult( 89 | widget: clazzInstance, state: ARouterResultState.FOUND); 90 | } catch (e) { 91 | return ARouterResult(state: ARouterResultState.NOT_FOUND); 92 | } 93 | } 94 | 95 | dynamic findPageConfig(ARouteOption option) { 96 | final List> pageConfigList = 97 | innerRouterMap[option.urlpattern]; 98 | if (null != pageConfigList) { 99 | for (int i = 0; i < pageConfigList.length; i++) { 100 | final Map pageConfig = pageConfigList[i]; 101 | final String paramsString = pageConfig['params']; 102 | if (null != paramsString) { 103 | Map params; 104 | try { 105 | params = json.decode(paramsString); 106 | } catch (e) { 107 | print('not found A{pageConfig};'); 108 | } 109 | if (null != params) { 110 | bool match = true; 111 | final Function matchParams = (String k, dynamic v) { 112 | if (params[k] != option?.params[k]) { 113 | match = false; 114 | print('not match:A{params[k]}:A{option?.params[k]}'); 115 | } 116 | }; 117 | params.forEach(matchParams); 118 | if (match) { 119 | return pageConfig; 120 | } 121 | } else { 122 | print('ERROR: in parsing paramsA{pageConfig}'); 123 | } 124 | } else { 125 | return pageConfig; 126 | } 127 | } 128 | } 129 | return null; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /lib/route.dart: -------------------------------------------------------------------------------- 1 | class ARoute { 2 | final String desc; 3 | final String url; 4 | final Map params; 5 | final List alias; 6 | const ARoute({this.desc, this.url, this.params, this.alias}); 7 | } 8 | 9 | class ARouteRoot { 10 | const ARouteRoot(); 11 | } 12 | 13 | class ARouteAlias { 14 | final String desc; 15 | final String url; 16 | final Map params; 17 | const ARouteAlias({this.desc, this.url, this.params}); 18 | } 19 | 20 | class ARouteOption { 21 | String urlpattern; 22 | Map params; 23 | ARouteOption(this.urlpattern, this.params); 24 | } 25 | 26 | enum ARouterResultState { FOUND, REDIRECT, NOT_FOUND } 27 | 28 | class ARouterResult { 29 | dynamic widget; 30 | String interceptor; 31 | ARouterResultState state; 32 | ARouterResult({this.state, this.widget, this.interceptor}); 33 | } 34 | 35 | abstract class ARouterInternal { 36 | bool hasPageConfig(ARouteOption option); 37 | ARouterResult findPage(ARouteOption option, dynamic initOption); 38 | } 39 | -------------------------------------------------------------------------------- /lib/src/collector.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' hide JsonDecoder; 2 | 3 | import 'package:analyzer/dart/element/element.dart'; 4 | import 'package:build/src/builder/build_step.dart'; 5 | import 'package:source_gen/source_gen.dart'; 6 | import 'package:analyzer/dart/constant/value.dart'; 7 | import 'page_config_map_util.dart'; 8 | 9 | class Collector { 10 | Collector(); 11 | Map>> routerMap = 12 | >>{}; 13 | List importList = []; 14 | 15 | Map toStringDartObjectMap( 16 | Map map) { 17 | return map.map((DartObject k, DartObject v) { 18 | return MapEntry(k.toStringValue(), v); 19 | }); 20 | } 21 | 22 | Map toStringStringMap(Map map) { 23 | return map.map((DartObject k, DartObject v) { 24 | return MapEntry(k.toStringValue(), v.toStringValue()); 25 | }); 26 | } 27 | 28 | void collect( 29 | ClassElement element, ConstantReader annotation, BuildStep buildStep) { 30 | final String className = element.name; 31 | final String url = annotation.peek('url')?.stringValue; 32 | if (url != null) { 33 | addEntryFromPageConfig(annotation, className); 34 | } 35 | final ConstantReader alias = annotation.peek('alias'); 36 | if (alias != null) { 37 | final List aliasList = alias.listValue; 38 | final Function addEntry = (DartObject one) { 39 | final ConstantReader oneObj = ConstantReader(one); 40 | addEntryFromPageConfig(oneObj, className); 41 | }; 42 | aliasList.forEach(addEntry); 43 | } 44 | 45 | if (buildStep.inputId.path.contains('lib/')) { 46 | print(buildStep.inputId.path); 47 | importClazz( 48 | "package:${buildStep.inputId.package}/${buildStep.inputId.path.replaceFirst('lib/', '')}"); 49 | } else { 50 | importClazz("${buildStep.inputId.path}"); 51 | } 52 | } 53 | 54 | void addEntryFromPageConfig(ConstantReader reader, String className) { 55 | final String url = reader.peek('url')?.stringValue; 56 | if (url != null) { 57 | final Map map = 58 | genPageConfigFromConstantReader(reader, className); 59 | if (map != null) { 60 | addEntry("'${url}'", map); 61 | } 62 | } 63 | } 64 | 65 | Map genPageConfigFromConstantReader( 66 | ConstantReader reader, String className) { 67 | final ConstantReader params = reader.peek('params'); 68 | final Map map = {wK('clazz'): className}; 69 | if (params != null) { 70 | final Map paramsMap = toStringStringMap(params.mapValue); 71 | map[wK('params')] = "${wK(json.encode(paramsMap))}"; 72 | } 73 | return map; 74 | } 75 | 76 | void addEntry(String key, Map value) { 77 | List> list = routerMap[key]; 78 | if (null == list) { 79 | list = >[]; 80 | routerMap[key] = list; 81 | } 82 | list.add(value); 83 | } 84 | 85 | void importClazz(String path) { 86 | importList.add(path); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /lib/src/page_config_map_util.dart: -------------------------------------------------------------------------------- 1 | String wK(String key) { 2 | return "'${key}'"; 3 | } 4 | -------------------------------------------------------------------------------- /lib/src/route_generator.dart: -------------------------------------------------------------------------------- 1 | import 'package:analyzer/dart/element/element.dart'; 2 | import 'package:build/src/builder/build_step.dart'; 3 | import 'package:source_gen/source_gen.dart'; 4 | import 'package:build/build.dart'; 5 | 6 | import '../route.dart'; 7 | import 'collector.dart'; 8 | import 'writer.dart'; 9 | 10 | class RouteWriterGenerator extends GeneratorForAnnotation { 11 | Collector collector() { 12 | return RouteGenerator.collector; 13 | } 14 | 15 | @override 16 | dynamic generateForAnnotatedElement( 17 | Element element, ConstantReader annotation, BuildStep buildStep) { 18 | return Writer(collector()).write(); 19 | } 20 | } 21 | 22 | class RouteGenerator extends GeneratorForAnnotation { 23 | static Collector collector = Collector(); 24 | 25 | @override 26 | dynamic generateForAnnotatedElement( 27 | Element element, ConstantReader annotation, BuildStep buildStep) { 28 | collector.collect(element, annotation, buildStep); 29 | return null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/tpl.dart: -------------------------------------------------------------------------------- 1 | const String clazzTpl = """ 2 | import 'dart:convert'; 3 | import 'package:annotation_route/route.dart'; 4 | {{#refs}} 5 | import '{{{path}}}'; 6 | {{/refs}} 7 | 8 | class ARouterInternalImpl extends ARouterInternal { 9 | ARouterInternalImpl(); 10 | final Map>> innerRouterMap = >>{{{routerMap}}}; 11 | 12 | @override 13 | bool hasPageConfig(ARouteOption option) { 14 | final dynamic pageConfig = findPageConfig(option); 15 | return pageConfig != null; 16 | } 17 | 18 | @override 19 | ARouterResult findPage(ARouteOption option, dynamic initOption) { 20 | final dynamic pageConfig = findPageConfig(option); 21 | if(pageConfig != null) { 22 | return implFromPageConfig(pageConfig, initOption); 23 | } else { 24 | return ARouterResult(state: ARouterResultState.NOT_FOUND); 25 | } 26 | } 27 | 28 | void instanceCreated(dynamic clazzInstance, Map pageConfig) { 29 | {{{instanceCreated}}} 30 | } 31 | 32 | dynamic instanceFromClazz(Type clazz, dynamic option) { 33 | {{{instanceFromClazz}}} 34 | } 35 | 36 | ARouterResult implFromPageConfig(Map pageConfig, dynamic option) { 37 | final String interceptor = pageConfig['interceptor']; 38 | if(interceptor != null) { 39 | return ARouterResult(state: ARouterResultState.REDIRECT, interceptor: interceptor); 40 | } 41 | final Type clazz = pageConfig['clazz']; 42 | if (clazz == null) { 43 | return ARouterResult(state: ARouterResultState.NOT_FOUND); 44 | } 45 | try { 46 | final dynamic clazzInstance = instanceFromClazz(clazz, option); 47 | instanceCreated(clazzInstance, pageConfig); 48 | return ARouterResult(widget: clazzInstance, state: ARouterResultState.FOUND); 49 | } catch (e) { 50 | return ARouterResult(state: ARouterResultState.NOT_FOUND); 51 | } 52 | } 53 | 54 | dynamic findPageConfig(ARouteOption option) { 55 | final List> pageConfigList = innerRouterMap[option.urlpattern]; 56 | if (null != pageConfigList) { 57 | for (int i = 0; i < pageConfigList.length; i++) { 58 | final Map pageConfig = pageConfigList[i]; 59 | final String paramsString = pageConfig['params']; 60 | if (null != paramsString) { 61 | Map params; 62 | try { 63 | params = json.decode(paramsString); 64 | } catch (e) { 65 | print('not found A{pageConfig};'); 66 | } 67 | if (null != params) { 68 | bool match = true; 69 | final Function matchParams = (String k, dynamic v) { 70 | if (params[k] != option?.params[k]) { 71 | match = false; 72 | print('not match:A{params[k]}:A{option?.params[k]}'); 73 | } 74 | }; 75 | params.forEach(matchParams); 76 | if (match) { 77 | return pageConfig; 78 | } 79 | } else { 80 | print('ERROR: in parsing paramsA{pageConfig}'); 81 | } 82 | } else { 83 | return pageConfig; 84 | } 85 | } 86 | } 87 | return null; 88 | } 89 | } 90 | """; 91 | 92 | const String instanceCreatedTpl = """ 93 | """; 94 | -------------------------------------------------------------------------------- /lib/src/writer.dart: -------------------------------------------------------------------------------- 1 | import 'package:mustache4dart/mustache4dart.dart'; 2 | import 'collector.dart'; 3 | import 'page_config_map_util.dart'; 4 | import 'tpl.dart'; 5 | 6 | class Writer { 7 | Collector collector; 8 | Writer(this.collector); 9 | 10 | String instanceCreated() { 11 | return instanceCreatedTpl; 12 | } 13 | 14 | String instanceFromClazz() { 15 | final StringBuffer buffer = new StringBuffer(); 16 | buffer..writeln('switch(clazz) {'); 17 | final Map mappedClazz = {}; 18 | final Function writeClazzCase = (Map config) { 19 | final dynamic clazz = config[wK('clazz')]; 20 | if (mappedClazz[clazz] == null) { 21 | mappedClazz[clazz] = true; 22 | } else { 23 | return; 24 | } 25 | buffer.writeln('case ${clazz}: return new ${clazz}(option);'); 26 | }; 27 | collector.routerMap 28 | .forEach((String url, List> configList) { 29 | configList.forEach(writeClazzCase); 30 | }); 31 | buffer..writeln('default:return null;')..writeln('}'); 32 | return buffer.toString(); 33 | } 34 | 35 | String write() { 36 | final List> refs = >[]; 37 | final Function addRef = (String path) { 38 | refs.add({'path': path}); 39 | }; 40 | collector.importList.forEach(addRef); 41 | return render(clazzTpl, { 42 | 'refs': refs, 43 | 'instanceCreated': instanceCreated(), 44 | 'instanceFromClazz': instanceFromClazz(), 45 | 'routerMap': collector.routerMap.toString() 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://www.dartlang.org/tools/pub/glossary#lockfile 3 | packages: 4 | analyzer: 5 | dependency: "direct main" 6 | description: 7 | name: analyzer 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "0.32.6" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.5.0" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.0.8" 25 | boolean_selector: 26 | dependency: transitive 27 | description: 28 | name: boolean_selector 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.0.4" 32 | build: 33 | dependency: "direct main" 34 | description: 35 | name: build 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "0.12.7+3" 39 | build_config: 40 | dependency: "direct main" 41 | description: 42 | name: build_config 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "0.3.1+4" 46 | build_resolvers: 47 | dependency: transitive 48 | description: 49 | name: build_resolvers 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "0.2.2+1" 53 | build_runner: 54 | dependency: "direct dev" 55 | description: 56 | name: build_runner 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "0.10.1" 60 | build_runner_core: 61 | dependency: transitive 62 | description: 63 | name: build_runner_core 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "0.3.1+2" 67 | built_collection: 68 | dependency: transitive 69 | description: 70 | name: built_collection 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "3.1.3" 74 | built_value: 75 | dependency: transitive 76 | description: 77 | name: built_value 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "6.1.5" 81 | charcode: 82 | dependency: transitive 83 | description: 84 | name: charcode 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "1.1.2" 88 | cli_util: 89 | dependency: transitive 90 | description: 91 | name: cli_util 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "0.1.3+2" 95 | code_builder: 96 | dependency: transitive 97 | description: 98 | name: code_builder 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "3.1.3" 102 | collection: 103 | dependency: transitive 104 | description: 105 | name: collection 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "1.14.11" 109 | convert: 110 | dependency: transitive 111 | description: 112 | name: convert 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "2.0.2" 116 | crypto: 117 | dependency: transitive 118 | description: 119 | name: crypto 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "2.0.6" 123 | csslib: 124 | dependency: transitive 125 | description: 126 | name: csslib 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "0.14.6" 130 | dart_style: 131 | dependency: transitive 132 | description: 133 | name: dart_style 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "1.1.3" 137 | fixnum: 138 | dependency: transitive 139 | description: 140 | name: fixnum 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "0.10.8" 144 | front_end: 145 | dependency: transitive 146 | description: 147 | name: front_end 148 | url: "https://pub.dartlang.org" 149 | source: hosted 150 | version: "0.1.4+2" 151 | glob: 152 | dependency: transitive 153 | description: 154 | name: glob 155 | url: "https://pub.dartlang.org" 156 | source: hosted 157 | version: "1.1.7" 158 | graphs: 159 | dependency: transitive 160 | description: 161 | name: graphs 162 | url: "https://pub.dartlang.org" 163 | source: hosted 164 | version: "0.1.2+1" 165 | html: 166 | dependency: transitive 167 | description: 168 | name: html 169 | url: "https://pub.dartlang.org" 170 | source: hosted 171 | version: "0.13.3+3" 172 | http: 173 | dependency: transitive 174 | description: 175 | name: http 176 | url: "https://pub.dartlang.org" 177 | source: hosted 178 | version: "0.12.0" 179 | http_multi_server: 180 | dependency: transitive 181 | description: 182 | name: http_multi_server 183 | url: "https://pub.dartlang.org" 184 | source: hosted 185 | version: "2.0.5" 186 | http_parser: 187 | dependency: transitive 188 | description: 189 | name: http_parser 190 | url: "https://pub.dartlang.org" 191 | source: hosted 192 | version: "3.1.3" 193 | io: 194 | dependency: transitive 195 | description: 196 | name: io 197 | url: "https://pub.dartlang.org" 198 | source: hosted 199 | version: "0.3.3" 200 | js: 201 | dependency: transitive 202 | description: 203 | name: js 204 | url: "https://pub.dartlang.org" 205 | source: hosted 206 | version: "0.6.1+1" 207 | json_annotation: 208 | dependency: transitive 209 | description: 210 | name: json_annotation 211 | url: "https://pub.dartlang.org" 212 | source: hosted 213 | version: "1.2.0" 214 | json_rpc_2: 215 | dependency: transitive 216 | description: 217 | name: json_rpc_2 218 | url: "https://pub.dartlang.org" 219 | source: hosted 220 | version: "2.0.9" 221 | kernel: 222 | dependency: transitive 223 | description: 224 | name: kernel 225 | url: "https://pub.dartlang.org" 226 | source: hosted 227 | version: "0.3.4+2" 228 | logging: 229 | dependency: transitive 230 | description: 231 | name: logging 232 | url: "https://pub.dartlang.org" 233 | source: hosted 234 | version: "0.11.3+2" 235 | matcher: 236 | dependency: transitive 237 | description: 238 | name: matcher 239 | url: "https://pub.dartlang.org" 240 | source: hosted 241 | version: "0.12.3+1" 242 | meta: 243 | dependency: transitive 244 | description: 245 | name: meta 246 | url: "https://pub.dartlang.org" 247 | source: hosted 248 | version: "1.1.6" 249 | mime: 250 | dependency: transitive 251 | description: 252 | name: mime 253 | url: "https://pub.dartlang.org" 254 | source: hosted 255 | version: "0.9.6+2" 256 | multi_server_socket: 257 | dependency: transitive 258 | description: 259 | name: multi_server_socket 260 | url: "https://pub.dartlang.org" 261 | source: hosted 262 | version: "1.0.2" 263 | mustache4dart: 264 | dependency: "direct main" 265 | description: 266 | name: mustache4dart 267 | url: "https://pub.dartlang.org" 268 | source: hosted 269 | version: "3.0.0-dev.1.0" 270 | node_preamble: 271 | dependency: transitive 272 | description: 273 | name: node_preamble 274 | url: "https://pub.dartlang.org" 275 | source: hosted 276 | version: "1.4.4" 277 | package_config: 278 | dependency: transitive 279 | description: 280 | name: package_config 281 | url: "https://pub.dartlang.org" 282 | source: hosted 283 | version: "1.0.5" 284 | package_resolver: 285 | dependency: transitive 286 | description: 287 | name: package_resolver 288 | url: "https://pub.dartlang.org" 289 | source: hosted 290 | version: "1.0.6" 291 | path: 292 | dependency: transitive 293 | description: 294 | name: path 295 | url: "https://pub.dartlang.org" 296 | source: hosted 297 | version: "1.6.2" 298 | plugin: 299 | dependency: transitive 300 | description: 301 | name: plugin 302 | url: "https://pub.dartlang.org" 303 | source: hosted 304 | version: "0.2.0+3" 305 | pool: 306 | dependency: transitive 307 | description: 308 | name: pool 309 | url: "https://pub.dartlang.org" 310 | source: hosted 311 | version: "1.3.6" 312 | pub_semver: 313 | dependency: transitive 314 | description: 315 | name: pub_semver 316 | url: "https://pub.dartlang.org" 317 | source: hosted 318 | version: "1.4.2" 319 | pubspec_parse: 320 | dependency: transitive 321 | description: 322 | name: pubspec_parse 323 | url: "https://pub.dartlang.org" 324 | source: hosted 325 | version: "0.1.2+2" 326 | quiver: 327 | dependency: transitive 328 | description: 329 | name: quiver 330 | url: "https://pub.dartlang.org" 331 | source: hosted 332 | version: "2.0.1" 333 | reflectable: 334 | dependency: transitive 335 | description: 336 | name: reflectable 337 | url: "https://pub.dartlang.org" 338 | source: hosted 339 | version: "2.0.7" 340 | shelf: 341 | dependency: transitive 342 | description: 343 | name: shelf 344 | url: "https://pub.dartlang.org" 345 | source: hosted 346 | version: "0.7.3+3" 347 | shelf_packages_handler: 348 | dependency: transitive 349 | description: 350 | name: shelf_packages_handler 351 | url: "https://pub.dartlang.org" 352 | source: hosted 353 | version: "1.0.4" 354 | shelf_static: 355 | dependency: transitive 356 | description: 357 | name: shelf_static 358 | url: "https://pub.dartlang.org" 359 | source: hosted 360 | version: "0.2.8" 361 | shelf_web_socket: 362 | dependency: transitive 363 | description: 364 | name: shelf_web_socket 365 | url: "https://pub.dartlang.org" 366 | source: hosted 367 | version: "0.2.2+4" 368 | source_gen: 369 | dependency: "direct main" 370 | description: 371 | name: source_gen 372 | url: "https://pub.dartlang.org" 373 | source: hosted 374 | version: "0.9.0+1" 375 | source_map_stack_trace: 376 | dependency: transitive 377 | description: 378 | name: source_map_stack_trace 379 | url: "https://pub.dartlang.org" 380 | source: hosted 381 | version: "1.1.5" 382 | source_maps: 383 | dependency: transitive 384 | description: 385 | name: source_maps 386 | url: "https://pub.dartlang.org" 387 | source: hosted 388 | version: "0.10.8" 389 | source_span: 390 | dependency: transitive 391 | description: 392 | name: source_span 393 | url: "https://pub.dartlang.org" 394 | source: hosted 395 | version: "1.4.1" 396 | stack_trace: 397 | dependency: transitive 398 | description: 399 | name: stack_trace 400 | url: "https://pub.dartlang.org" 401 | source: hosted 402 | version: "1.9.3" 403 | stream_channel: 404 | dependency: transitive 405 | description: 406 | name: stream_channel 407 | url: "https://pub.dartlang.org" 408 | source: hosted 409 | version: "1.6.8" 410 | stream_transform: 411 | dependency: transitive 412 | description: 413 | name: stream_transform 414 | url: "https://pub.dartlang.org" 415 | source: hosted 416 | version: "0.0.14+1" 417 | string_scanner: 418 | dependency: transitive 419 | description: 420 | name: string_scanner 421 | url: "https://pub.dartlang.org" 422 | source: hosted 423 | version: "1.0.4" 424 | term_glyph: 425 | dependency: transitive 426 | description: 427 | name: term_glyph 428 | url: "https://pub.dartlang.org" 429 | source: hosted 430 | version: "1.0.1" 431 | test: 432 | dependency: "direct dev" 433 | description: 434 | name: test 435 | url: "https://pub.dartlang.org" 436 | source: hosted 437 | version: "1.3.3" 438 | typed_data: 439 | dependency: transitive 440 | description: 441 | name: typed_data 442 | url: "https://pub.dartlang.org" 443 | source: hosted 444 | version: "1.1.6" 445 | utf: 446 | dependency: transitive 447 | description: 448 | name: utf 449 | url: "https://pub.dartlang.org" 450 | source: hosted 451 | version: "0.9.0+5" 452 | vm_service_client: 453 | dependency: transitive 454 | description: 455 | name: vm_service_client 456 | url: "https://pub.dartlang.org" 457 | source: hosted 458 | version: "0.2.6" 459 | watcher: 460 | dependency: transitive 461 | description: 462 | name: watcher 463 | url: "https://pub.dartlang.org" 464 | source: hosted 465 | version: "0.9.7+10" 466 | web_socket_channel: 467 | dependency: transitive 468 | description: 469 | name: web_socket_channel 470 | url: "https://pub.dartlang.org" 471 | source: hosted 472 | version: "1.0.9" 473 | yaml: 474 | dependency: transitive 475 | description: 476 | name: yaml 477 | url: "https://pub.dartlang.org" 478 | source: hosted 479 | version: "2.1.15" 480 | sdks: 481 | dart: ">=2.0.0 <3.0.0" 482 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: annotation_route 2 | description: auto generate router config 3 | version: 0.0.2 4 | author: voicewitness 5 | homepage: https://github.com/alibaba-flutter/annotation_route 6 | dependencies: 7 | analyzer: any 8 | build: any 9 | source_gen: '>=0.8.0' 10 | build_config: '>=0.3.0' 11 | mustache4dart: any 12 | dev_dependencies: 13 | build_runner: '>=0.9.1' 14 | test: any 15 | 16 | environment: 17 | sdk: '>=2.0.0 <3.0.0' 18 | --------------------------------------------------------------------------------