From 6760cbc8de5a3f2c003aef42bab8f58173148a71 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 21 Jul 2017 14:47:09 -0700 Subject: [PATCH] Generate with LibraryReader over LibraryElement Similar to ConstantReader this will make it easier to use new utility methods as we add them. - Make `_element` public so that clients can still access the `LibraryElement` when needed. - Change the `generate` method signature and all implementations. - Wrap the argument in `builder.dart`. --- CHANGELOG.md | 5 +++-- lib/src/builder.dart | 4 +++- lib/src/generator.dart | 5 +++-- lib/src/generator_for_annotation.dart | 5 ++--- lib/src/library.dart | 16 ++++++++-------- test/builder_test.dart | 5 ++--- test/src/comment_generator.dart | 9 ++++----- test/src/unformatted_code_generator.dart | 3 +-- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34a05eb0..cd2daf45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,9 @@ ## 0.7.0 * **Breaking changes** - * `Generator.generate` now operates on a `LibraryElement` rather than being + * `Generator.generate` now operates on a `LibraryReader` rather than being called for every `Element` within a library. Generators can iterate over - elements using the `allElements` utility. `GeneratorForAnnotation` will + elements using `LibraryReader.allElements`. `GeneratorForAnnotation` will continue to call `generateForAnnotatedElement` repeatedly for each element. * `GeneratorForAnnotation` passes in a `ConstantReader` for the annotation instance rather than re-creating it using mirrors. @@ -15,6 +15,7 @@ * Removed `OutputFormatter` typedef. * Add `LibraryReader.allElements` - a utility to iterate across all `Element` instances contained in Dart library. +* Add `LibraryReader.element` to get back to the `LibraryElement` instance. ## 0.6.1+1 diff --git a/lib/src/builder.dart b/lib/src/builder.dart index 336a194e..df0b7f6e 100644 --- a/lib/src/builder.dart +++ b/lib/src/builder.dart @@ -10,6 +10,7 @@ import 'package:dart_style/dart_style.dart'; import 'generated_output.dart'; import 'generator.dart'; +import 'library.dart'; import 'utils.dart'; typedef String _OutputFormatter(String code); @@ -195,10 +196,11 @@ class LibraryBuilder extends _Builder { Stream _generate(LibraryElement library, List generators, BuildStep buildStep) async* { + var libraryReader = new LibraryReader(library); for (var gen in generators) { try { log.finer('Running $gen for $library'); - var createdUnit = await gen.generate(library, buildStep); + var createdUnit = await gen.generate(libraryReader, buildStep); if (createdUnit != null && createdUnit.isNotEmpty) { log.finest(() => 'Generated $createdUnit for $library'); diff --git a/lib/src/generator.dart b/lib/src/generator.dart index a13a1879..84636e62 100644 --- a/lib/src/generator.dart +++ b/lib/src/generator.dart @@ -4,9 +4,10 @@ import 'dart:async'; -import 'package:analyzer/dart/element/element.dart'; import 'package:build/build.dart'; +import 'library.dart'; + /// A tool to generate Dart code based on a Dart library source. /// /// During a build [generate] is called once per input library. @@ -19,7 +20,7 @@ abstract class Generator { /// output is Dart code returned through the Future. If there is nothing to /// generate for this library may return null, or a Future that resolves to /// null or the empty string. - Future generate(LibraryElement element, BuildStep buildStep) => null; + Future generate(LibraryReader library, BuildStep buildStep) => null; @override String toString() => this.runtimeType.toString(); diff --git a/lib/src/generator_for_annotation.dart b/lib/src/generator_for_annotation.dart index 83ef650e..f0991c59 100644 --- a/lib/src/generator_for_annotation.dart +++ b/lib/src/generator_for_annotation.dart @@ -35,9 +35,8 @@ abstract class GeneratorForAnnotation extends Generator { TypeChecker get typeChecker => new TypeChecker.fromRuntime(T); @override - Future generate(LibraryElement library, BuildStep buildStep) async { - var elements = new LibraryReader(library) - .allElements + Future generate(LibraryReader library, BuildStep buildStep) async { + var elements = library.allElements .map((e) => new _AnnotatedElement(e, typeChecker.firstAnnotationOf(e))) .where((e) => e.annotation != null); var allOutput = await Future.wait(elements.map((e) => diff --git a/lib/src/library.dart b/lib/src/library.dart index ed3d40bd..c8a68c70 100644 --- a/lib/src/library.dart +++ b/lib/src/library.dart @@ -10,27 +10,27 @@ import 'package:analyzer/src/dart/resolver/scope.dart'; /// A high-level wrapper API with common functionality for [LibraryElement]. class LibraryReader { - final LibraryElement _element; + final LibraryElement element; Namespace _namespaceCache; - LibraryReader(this._element); + LibraryReader(this.element); Namespace get _namespace => _namespaceCache ??= - new NamespaceBuilder().createExportNamespaceForLibrary(_element); + new NamespaceBuilder().createExportNamespaceForLibrary(element); /// Returns a top-level [ClassElement] publicly visible in by [name]. /// /// Unlike [LibraryElement.getType], this also correctly traverses identifiers /// that are accessible via one or more `export` directives. ClassElement findType(String name) => - _element.getType(name) ?? _namespace.get(name) as ClassElement; + element.getType(name) ?? _namespace.get(name) as ClassElement; - /// Returns all of the declarations in this library, including the - /// [LibraryElement] as the first item. + /// All of the declarations in this library, including the [LibraryElement] as + /// the first item. Iterable get allElements sync* { - yield _element; - for (var cu in _element.units) { + yield element; + for (var cu in element.units) { for (var compUnitMember in cu.unit.declarations) { yield* _getElements(compUnitMember); } diff --git a/test/builder_test.dart b/test/builder_test.dart index 9d204701..23a13880 100644 --- a/test/builder_test.dart +++ b/test/builder_test.dart @@ -5,7 +5,6 @@ @TestOn('vm') import 'dart:async'; -import 'package:analyzer/dart/element/element.dart'; import 'package:build_test/build_test.dart'; import 'package:source_gen/source_gen.dart'; import 'package:test/test.dart'; @@ -175,12 +174,12 @@ Map _createPackageStub(String pkgName, /// Doesn't generate output for any element class _NoOpGenerator extends Generator { const _NoOpGenerator(); - Future generate(LibraryElement element, _) => null; + Future generate(LibraryReader library, _) => null; } class _BadOutputGenerator extends Generator { const _BadOutputGenerator(); - Future generate(LibraryElement element, _) async => 'not valid code!'; + Future generate(LibraryReader library, _) async => 'not valid code!'; } const pkgName = 'pkg'; diff --git a/test/src/comment_generator.dart b/test/src/comment_generator.dart index e637bee6..8e02c9ec 100644 --- a/test/src/comment_generator.dart +++ b/test/src/comment_generator.dart @@ -14,15 +14,14 @@ class CommentGenerator extends Generator { const CommentGenerator({this.forClasses: true, this.forLibrary: false}); @override - Future generate(LibraryElement library, _) async { + Future generate(LibraryReader library, _) async { var output = new StringBuffer(); if (forLibrary) { - output.writeln('// Code for "$library"'); + output.writeln('// Code for "${library.element}"'); } if (forClasses) { - for (var classElement in new LibraryReader(library) - .allElements - .where((e) => e is ClassElement)) { + for (var classElement + in library.allElements.where((e) => e is ClassElement)) { if (classElement.displayName.contains('GoodError')) { throw new InvalidGenerationSourceError( "Don't use classes with the word 'Error' in the name", diff --git a/test/src/unformatted_code_generator.dart b/test/src/unformatted_code_generator.dart index dae604a0..8dd122a1 100644 --- a/test/src/unformatted_code_generator.dart +++ b/test/src/unformatted_code_generator.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:analyzer/dart/element/element.dart'; import 'package:source_gen/source_gen.dart'; /// Generates a single-line of unformatted code. @@ -12,7 +11,7 @@ class UnformattedCodeGenerator extends Generator { const UnformattedCodeGenerator(); @override - Future generate(LibraryElement element, _) async => unformattedCode; + Future generate(LibraryReader library, _) async => unformattedCode; static const formattedCode = ''' void hello() => print('hello');