| Index: third_party/pkg/di/lib/generator.dart
|
| diff --git a/third_party/pkg/di/lib/generator.dart b/third_party/pkg/di/lib/generator.dart
|
| index 1266b432d76dddc2627728356affca012c2035c6..7ebb1a9c56ff5e8d5bf870ad9474b0a9108748b4 100644
|
| --- a/third_party/pkg/di/lib/generator.dart
|
| +++ b/third_party/pkg/di/lib/generator.dart
|
| @@ -7,13 +7,16 @@ import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
|
| import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
|
| import 'package:analyzer/src/generated/element.dart';
|
| import 'package:analyzer/src/generated/engine.dart';
|
| +import 'package:path/path.dart' as path;
|
|
|
| import 'dart:io';
|
|
|
| const String PACKAGE_PREFIX = 'package:';
|
| const String DART_PACKAGE_PREFIX = 'dart:';
|
| +const List<String> _DEFAULT_INJECTABLE_ANNOTATIONS =
|
| + const ['di.annotations.Injectable'];
|
|
|
| -main(args) {
|
| +main(List<String> args) {
|
| if (args.length < 4) {
|
| print('Usage: generator path_to_sdk file_to_resolve annotations output [package_roots+]');
|
| exit(0);
|
| @@ -21,7 +24,8 @@ main(args) {
|
|
|
| var pathToSdk = args[0];
|
| var entryPoint = args[1];
|
| - var classAnnotations = args[2].split(',');
|
| + var classAnnotations = args[2].split(',')
|
| + ..addAll(_DEFAULT_INJECTABLE_ANNOTATIONS);
|
| var output = args[3];
|
| var packageRoots = (args.length < 5) ? [Platform.packageRoot] : args.sublist(4);
|
|
|
| @@ -31,7 +35,7 @@ main(args) {
|
| print('output: $output');
|
| print('packageRoots: $packageRoots');
|
|
|
| - var code = generateCode(entryPoint, classAnnotations, pathToSdk, packageRoots);
|
| + var code = generateCode(entryPoint, classAnnotations, pathToSdk, packageRoots, output);
|
| code.forEach((chunk, code) {
|
| String fileName = output;
|
| if (chunk.library != null) {
|
| @@ -43,14 +47,14 @@ main(args) {
|
| }
|
|
|
| Map<Chunk, String> generateCode(String entryPoint, List<String> classAnnotations,
|
| - String pathToSdk, List<String> packageRoots) {
|
| + String pathToSdk, List<String> packageRoots, String outputFilename) {
|
| var c = new SourceCrawler(pathToSdk, packageRoots);
|
| List<String> imports = <String>[];
|
| Map<Chunk, List<ClassElement>> typeFactoryTypes = <Chunk, List<ClassElement>>{};
|
| Map<String, String> typeToImport = new Map<String, String>();
|
| c.crawl(entryPoint, (CompilationUnitElement compilationUnit, SourceFile source) {
|
| new CompilationUnitVisitor(c.context, source, classAnnotations, imports,
|
| - typeToImport, typeFactoryTypes).visit(compilationUnit, source);
|
| + typeToImport, typeFactoryTypes, outputFilename).visit(compilationUnit, source);
|
| });
|
| return printLibraryCode(typeToImport, imports, typeFactoryTypes);
|
| }
|
| @@ -69,30 +73,43 @@ Map<Chunk, String> printLibraryCode(Map<String, String> typeToImport,
|
| if (!requiredImports.contains(import)) {
|
| requiredImports.add(import);
|
| }
|
| - return 'import_${imports.indexOf(import)}.${type.name}';
|
| + String prefix = _calculateImportPrefix(import, imports);
|
| + return '$prefix.${type.name}';
|
| }
|
| factories[chunk] = new StringBuffer();
|
| classes.forEach((ClassElement clazz) {
|
| StringBuffer factory = new StringBuffer();
|
| bool skip = false;
|
| - factory.write(
|
| - '${resolveClassIdentifier(clazz.type)}: (f) => ');
|
| + factory.write('${resolveClassIdentifier(clazz.type)}: (f) => ');
|
| factory.write('new ${resolveClassIdentifier(clazz.type)}(');
|
| ConstructorElement constr =
|
| clazz.constructors.firstWhere((c) => c.name.isEmpty,
|
| orElse: () {
|
| - throw 'Unable to find default constructor for $clazz in ${clazz.source}';
|
| + throw 'Unable to find default constructor for '
|
| + '$clazz in ${clazz.source}';
|
| });
|
| factory.write(constr.parameters.map((param) {
|
| if (param.type.element is! ClassElement) {
|
| throw 'Unable to resolve type for constructor parameter '
|
| - '"${param.name}" for type "$clazz" in ${clazz.source}';
|
| + '"${param.name}" for type "$clazz" in ${clazz.source}';
|
| }
|
| if (_isParameterized(param)) {
|
| - print('WARNING: parameterized types are not supported: $param in $clazz in ${clazz.source}. Skipping!');
|
| + print('WARNING: parameterized types are not supported: '
|
| + '$param in $clazz in ${clazz.source}. Skipping!');
|
| skip = true;
|
| }
|
| - return 'f(${resolveClassIdentifier(param.type)})';
|
| + var annotations = [];
|
| + if (param.metadata.isNotEmpty) {
|
| + annotations = param.metadata.map(
|
| + (item) => resolveClassIdentifier(item.element.returnType));
|
| + }
|
| + StringBuffer output =
|
| + new StringBuffer('f(${resolveClassIdentifier(param.type)}');
|
| + if (annotations.isNotEmpty) {
|
| + output.write(', ${annotations.first}');
|
| + }
|
| + output.write(')');
|
| + return output;
|
| }).join(', '));
|
| factory.write('),\n');
|
| if (!skip) {
|
| @@ -103,7 +120,8 @@ Map<Chunk, String> printLibraryCode(Map<String, String> typeToImport,
|
| String libSuffix = chunk.library == null ? '' : '.${chunk.library.name}';
|
| code.write('library di.generated.type_factories$libSuffix;\n');
|
| requiredImports.forEach((import) {
|
| - code.write ('import "$import" as import_${imports.indexOf(import)};\n');
|
| + String prefix = _calculateImportPrefix(import, imports);
|
| + code.write ('import "$import" as $prefix;\n');
|
| });
|
| code..write('var typeFactories = {\n${factories[chunk]}\n};\n')
|
| ..write('main() {}\n');
|
| @@ -113,6 +131,9 @@ Map<Chunk, String> printLibraryCode(Map<String, String> typeToImport,
|
| return result;
|
| }
|
|
|
| +String _calculateImportPrefix(String import, List<String> imports) =>
|
| + 'import_${imports.indexOf(import)}';
|
| +
|
| _isParameterized(ParameterElement param) {
|
| String typeName = param.type.toString();
|
|
|
| @@ -131,12 +152,16 @@ class CompilationUnitVisitor {
|
| List<String> classAnnotations;
|
| SourceFile source;
|
| AnalysisContext context;
|
| + String outputFilename;
|
|
|
| CompilationUnitVisitor(this.context, this.source,
|
| this.classAnnotations, this.imports, this.typeToImport,
|
| - this.typeFactoryTypes);
|
| + this.typeFactoryTypes, this.outputFilename);
|
|
|
| visit(CompilationUnitElement compilationUnit, SourceFile source) {
|
| + if (typeFactoryTypes[source.chunk] == null) {
|
| + typeFactoryTypes[source.chunk] = <ClassElement>[];
|
| + }
|
| visitLibrary(compilationUnit.enclosingElement, source);
|
|
|
| List<ClassElement> types = <ClassElement>[];
|
| @@ -170,9 +195,6 @@ class CompilationUnitVisitor {
|
| throw 'Unable to resolve type "$expr" from @Injectables '
|
| 'in ${library.element.source}';
|
| }
|
| - if (typeFactoryTypes[source.chunk] == null) {
|
| - typeFactoryTypes[source.chunk] = <ClassElement>[];
|
| - }
|
| if (!typeFactoryTypes[source.chunk].contains(element)) {
|
| typeFactoryTypes[source.chunk].add(element as ClassElement);
|
| }
|
| @@ -188,10 +210,13 @@ class CompilationUnitVisitor {
|
| if (classElement.name.startsWith('_')) {
|
| return; // ignore private classes.
|
| }
|
| - typeToImport[getCanonicalName(classElement.type)] =
|
| - source.entryPointImport;
|
| - if (!imports.contains(source.entryPointImport)) {
|
| - imports.add(source.entryPointImport);
|
| + var importUri = source.entryPointImport;
|
| + if (Uri.parse(importUri).scheme == '') {
|
| + importUri = path.relative(importUri, from: path.dirname(outputFilename));
|
| + }
|
| + typeToImport[getCanonicalName(classElement.type)] = importUri;
|
| + if (!imports.contains(importUri)) {
|
| + imports.add(importUri);
|
| }
|
| for (ElementAnnotation ann in classElement.metadata) {
|
| if (ann.element is ConstructorElement) {
|
| @@ -232,13 +257,14 @@ class SourceCrawler {
|
|
|
| SourceCrawler(this.sdkPath, this.packageRoots);
|
|
|
| - void crawl(String entryPoint, CompilationUnitCrawler _visitor) {
|
| + void crawl(String entryPoint, CompilationUnitCrawler _visitor,
|
| + {bool preserveComments : false}) {
|
| JavaSystemIO.setProperty("com.google.dart.sdk", sdkPath);
|
| DartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
|
|
|
| AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
|
| contextOptions.cacheSize = 256;
|
| - contextOptions.preserveComments = false;
|
| + contextOptions.preserveComments = preserveComments;
|
| contextOptions.analyzeFunctionBodies = false;
|
| context.analysisOptions = contextOptions;
|
| sdk.context.analysisOptions = contextOptions;
|
| @@ -246,7 +272,7 @@ class SourceCrawler {
|
| var packageUriResolver =
|
| new PackageUriResolver(packageRoots.map(
|
| (pr) => new JavaFile.fromUri(new Uri.file(pr))).toList());
|
| - context.sourceFactory = new SourceFactory.con2([
|
| + context.sourceFactory = new SourceFactory([
|
| new DartUriResolver(sdk),
|
| new FileUriResolver(),
|
| packageUriResolver
|
| @@ -256,18 +282,16 @@ class SourceCrawler {
|
| var entryPointImport;
|
| if (entryPoint.startsWith(PACKAGE_PREFIX)) {
|
| entryPointFile = new JavaFile(packageUriResolver
|
| - .resolveAbsolute(context.sourceFactory.contentCache,
|
| - Uri.parse(entryPoint)).toString());
|
| + .resolveAbsolute(Uri.parse(entryPoint)).toString());
|
| entryPointImport = entryPoint;
|
| } else {
|
| entryPointFile = new JavaFile(entryPoint);
|
| entryPointImport = entryPointFile.getAbsolutePath();
|
| }
|
|
|
| - Source source = new FileBasedSource.con1(
|
| - context.sourceFactory.contentCache, entryPointFile);
|
| + Source source = new FileBasedSource.con1(entryPointFile);
|
| ChangeSet changeSet = new ChangeSet();
|
| - changeSet.added(source);
|
| + changeSet.addedSource(source);
|
| context.applyChanges(changeSet);
|
| LibraryElement rootLib = context.computeLibraryElement(source);
|
| CompilationUnit resolvedUnit =
|
|
|