diff --git a/built_value_generator/lib/built_value_generator.dart b/built_value_generator/lib/built_value_generator.dart index 9f517878..66d7d4e4 100644 --- a/built_value_generator/lib/built_value_generator.dart +++ b/built_value_generator/lib/built_value_generator.dart @@ -5,8 +5,9 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:build/build.dart'; import 'package:built_value_generator/src/enum_source_library.dart'; -import 'package:built_value_generator/src/value_source_class.dart'; +import 'package:built_value_generator/src/parsed_library_results.dart'; import 'package:built_value_generator/src/serializer_source_library.dart'; +import 'package:built_value_generator/src/value_source_class.dart'; import 'package:source_gen/source_gen.dart'; /// Generator for Enum Class and Built Values. @@ -18,6 +19,8 @@ class BuiltValueGenerator extends Generator { @override Future generate(LibraryReader library, BuildStep buildStep) async { + var parsedLibraryResults = ParsedLibraryResults(); + // Workaround for https://github.com/google/built_value.dart/issues/941. LibraryElement libraryElement; var attempts = 0; @@ -25,7 +28,7 @@ class BuiltValueGenerator extends Generator { try { libraryElement = await buildStep.resolver.libraryFor( await buildStep.resolver.assetIdForElement(library.element)); - libraryElement.session.getParsedLibraryByElement(libraryElement); + parsedLibraryResults.parsedLibraryResultOrThrowingMock(libraryElement); break; } catch (_) { ++attempts; @@ -38,9 +41,11 @@ class BuiltValueGenerator extends Generator { var result = StringBuffer(); try { - final enumCode = EnumSourceLibrary(libraryElement).generateCode(); + final enumCode = EnumSourceLibrary(parsedLibraryResults, libraryElement) + .generateCode(); if (enumCode != null) result.writeln(enumCode); - final serializerSourceLibrary = SerializerSourceLibrary(libraryElement); + final serializerSourceLibrary = + SerializerSourceLibrary(parsedLibraryResults, libraryElement); if (serializerSourceLibrary.needsBuiltJson || serializerSourceLibrary.hasSerializers) { result.writeln(serializerSourceLibrary.generateCode()); @@ -64,7 +69,8 @@ class BuiltValueGenerator extends Generator { for (var element in libraryElement.units.expand((unit) => unit.classes)) { if (ValueSourceClass.needsBuiltValue(element)) { try { - result.writeln(ValueSourceClass(element).generateCode()); + result.writeln( + ValueSourceClass(parsedLibraryResults, element).generateCode()); } catch (e, st) { result.writeln(_error(e)); log.severe('Error in BuiltValueGenerator for $element.', e, st); diff --git a/built_value_generator/lib/src/analyzer.dart b/built_value_generator/lib/src/analyzer.dart deleted file mode 100644 index 7eed413c..00000000 --- a/built_value_generator/lib/src/analyzer.dart +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2021, Google Inc. Please see the AUTHORS file for details. -// All rights reserved. Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -import 'package:analyzer/dart/analysis/results.dart'; -import 'package:analyzer/dart/element/element.dart'; - -ParsedLibraryResult parsedLibraryResultOrThrowingMock(LibraryElement element) { - var result = element.session.getParsedLibraryByElement(element); - if (result is ParsedLibraryResult) { - return result; - } - return _ParsedLibraryResultMock(); -} - -class _ParsedLibraryResultMock implements ParsedLibraryResult { - @override - dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); -} diff --git a/built_value_generator/lib/src/dart_types.dart b/built_value_generator/lib/src/dart_types.dart index 834def73..a4f66e48 100644 --- a/built_value_generator/lib/src/dart_types.dart +++ b/built_value_generator/lib/src/dart_types.dart @@ -6,6 +6,7 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:built_value_generator/src/parsed_library_results.dart'; import 'package:built_value_generator/src/value_source_class.dart'; BuiltSet _builtCollectionNames = BuiltSet([ @@ -17,13 +18,18 @@ BuiltSet _builtCollectionNames = BuiltSet([ ]); class DartTypes { - static bool needsNestedBuilder(DartType type) { - return isInstantiableBuiltValue(type) || isBuiltCollection(type); + static bool needsNestedBuilder( + ParsedLibraryResults parsedLibraryResults, DartType type) { + return isInstantiableBuiltValue(parsedLibraryResults, type) || + isBuiltCollection(type); } - static bool isInstantiableBuiltValue(DartType type) { + static bool isInstantiableBuiltValue( + ParsedLibraryResults parsedLibraryResults, DartType type) { return isBuiltValue(type) && - ValueSourceClass(type.element as ClassElement).settings.instantiable; + ValueSourceClass(parsedLibraryResults, type.element as ClassElement) + .settings + .instantiable; } static bool isBuiltValue(DartType type) => diff --git a/built_value_generator/lib/src/enum_source_class.dart b/built_value_generator/lib/src/enum_source_class.dart index d468a811..ab37f41c 100644 --- a/built_value_generator/lib/src/enum_source_class.dart +++ b/built_value_generator/lib/src/enum_source_class.dart @@ -8,9 +8,9 @@ import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; -import 'package:built_value_generator/src/analyzer.dart'; import 'package:built_value_generator/src/dart_types.dart'; import 'package:built_value_generator/src/enum_source_field.dart'; +import 'package:built_value_generator/src/parsed_library_results.dart'; import 'package:built_value_generator/src/strings.dart'; import 'package:collection/collection.dart' show IterableExtension, IterableNullableExtension; @@ -21,16 +21,19 @@ part 'enum_source_class.g.dart'; abstract class EnumSourceClass implements Built { + ParsedLibraryResults get parsedLibraryResults; + InterfaceElement get element; - factory EnumSourceClass( - ParsedLibraryResult parsedLibrary, InterfaceElement element) => - _$EnumSourceClass._(element: element); + factory EnumSourceClass(ParsedLibraryResults parsedLibraryResults, + InterfaceElement element) => + _$EnumSourceClass._( + parsedLibraryResults: parsedLibraryResults, element: element); EnumSourceClass._(); @memoized ParsedLibraryResult get parsedLibrary => - parsedLibraryResultOrThrowingMock(element.library); + parsedLibraryResults.parsedLibraryResultOrThrowingMock(element.library); @memoized String get name => element.name; diff --git a/built_value_generator/lib/src/enum_source_class.g.dart b/built_value_generator/lib/src/enum_source_class.g.dart index 0c0510cc..0cf5aa3c 100644 --- a/built_value_generator/lib/src/enum_source_class.g.dart +++ b/built_value_generator/lib/src/enum_source_class.g.dart @@ -7,6 +7,8 @@ part of 'enum_source_class.dart'; // ************************************************************************** class _$EnumSourceClass extends EnumSourceClass { + @override + final ParsedLibraryResults parsedLibraryResults; @override final InterfaceElement element; ParsedLibraryResult? __parsedLibrary; @@ -26,7 +28,11 @@ class _$EnumSourceClass extends EnumSourceClass { factory _$EnumSourceClass([void Function(EnumSourceClassBuilder)? updates]) => (new EnumSourceClassBuilder()..update(updates))._build(); - _$EnumSourceClass._({required this.element}) : super._() { + _$EnumSourceClass._( + {required this.parsedLibraryResults, required this.element}) + : super._() { + BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, r'EnumSourceClass', 'parsedLibraryResults'); BuiltValueNullFieldError.checkNotNull( element, r'EnumSourceClass', 'element'); } @@ -88,12 +94,15 @@ class _$EnumSourceClass extends EnumSourceClass { @override bool operator ==(Object other) { if (identical(other, this)) return true; - return other is EnumSourceClass && element == other.element; + return other is EnumSourceClass && + parsedLibraryResults == other.parsedLibraryResults && + element == other.element; } @override int get hashCode { var _$hash = 0; + _$hash = $jc(_$hash, parsedLibraryResults.hashCode); _$hash = $jc(_$hash, element.hashCode); _$hash = $jf(_$hash); return _$hash; @@ -102,6 +111,7 @@ class _$EnumSourceClass extends EnumSourceClass { @override String toString() { return (newBuiltValueToStringHelper(r'EnumSourceClass') + ..add('parsedLibraryResults', parsedLibraryResults) ..add('element', element)) .toString(); } @@ -111,6 +121,12 @@ class EnumSourceClassBuilder implements Builder { _$EnumSourceClass? _$v; + ParsedLibraryResults? _parsedLibraryResults; + ParsedLibraryResults? get parsedLibraryResults => + _$this._parsedLibraryResults; + set parsedLibraryResults(ParsedLibraryResults? parsedLibraryResults) => + _$this._parsedLibraryResults = parsedLibraryResults; + InterfaceElement? _element; InterfaceElement? get element => _$this._element; set element(InterfaceElement? element) => _$this._element = element; @@ -120,6 +136,7 @@ class EnumSourceClassBuilder EnumSourceClassBuilder get _$this { final $v = _$v; if ($v != null) { + _parsedLibraryResults = $v.parsedLibraryResults; _element = $v.element; _$v = null; } @@ -143,6 +160,10 @@ class EnumSourceClassBuilder _$EnumSourceClass _build() { final _$result = _$v ?? new _$EnumSourceClass._( + parsedLibraryResults: BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, + r'EnumSourceClass', + 'parsedLibraryResults'), element: BuiltValueNullFieldError.checkNotNull( element, r'EnumSourceClass', 'element')); replace(_$result); diff --git a/built_value_generator/lib/src/enum_source_library.dart b/built_value_generator/lib/src/enum_source_library.dart index 6ce2e0c6..79912a9c 100644 --- a/built_value_generator/lib/src/enum_source_library.dart +++ b/built_value_generator/lib/src/enum_source_library.dart @@ -8,24 +8,27 @@ import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; -import 'package:built_value_generator/src/analyzer.dart'; import 'package:built_value_generator/src/enum_source_class.dart'; import 'package:built_value_generator/src/library_elements.dart'; +import 'package:built_value_generator/src/parsed_library_results.dart'; import 'package:source_gen/source_gen.dart'; part 'enum_source_library.g.dart'; abstract class EnumSourceLibrary implements Built { + ParsedLibraryResults get parsedLibraryResults; LibraryElement get element; - factory EnumSourceLibrary(LibraryElement element) => - _$EnumSourceLibrary._(element: element); + factory EnumSourceLibrary( + ParsedLibraryResults parsedLibraryResults, LibraryElement element) => + _$EnumSourceLibrary._( + parsedLibraryResults: parsedLibraryResults, element: element); EnumSourceLibrary._(); @memoized ParsedLibraryResult get parsedLibrary => - parsedLibraryResultOrThrowingMock(element.library); + parsedLibraryResults.parsedLibraryResultOrThrowingMock(element.library); @memoized String get name => element.name; @@ -42,7 +45,7 @@ abstract class EnumSourceLibrary for (var classElement in LibraryElements.getClassElements(element)) { if (EnumSourceClass.needsEnumClass(classElement)) { - result.add(EnumSourceClass(parsedLibrary, classElement)); + result.add(EnumSourceClass(parsedLibraryResults, classElement)); } } return result.build(); diff --git a/built_value_generator/lib/src/enum_source_library.g.dart b/built_value_generator/lib/src/enum_source_library.g.dart index 8f7c5665..97b3d1d0 100644 --- a/built_value_generator/lib/src/enum_source_library.g.dart +++ b/built_value_generator/lib/src/enum_source_library.g.dart @@ -7,6 +7,8 @@ part of 'enum_source_library.dart'; // ************************************************************************** class _$EnumSourceLibrary extends EnumSourceLibrary { + @override + final ParsedLibraryResults parsedLibraryResults; @override final LibraryElement element; ParsedLibraryResult? __parsedLibrary; @@ -19,7 +21,11 @@ class _$EnumSourceLibrary extends EnumSourceLibrary { [void Function(EnumSourceLibraryBuilder)? updates]) => (new EnumSourceLibraryBuilder()..update(updates))._build(); - _$EnumSourceLibrary._({required this.element}) : super._() { + _$EnumSourceLibrary._( + {required this.parsedLibraryResults, required this.element}) + : super._() { + BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, r'EnumSourceLibrary', 'parsedLibraryResults'); BuiltValueNullFieldError.checkNotNull( element, r'EnumSourceLibrary', 'element'); } @@ -51,12 +57,15 @@ class _$EnumSourceLibrary extends EnumSourceLibrary { @override bool operator ==(Object other) { if (identical(other, this)) return true; - return other is EnumSourceLibrary && element == other.element; + return other is EnumSourceLibrary && + parsedLibraryResults == other.parsedLibraryResults && + element == other.element; } @override int get hashCode { var _$hash = 0; + _$hash = $jc(_$hash, parsedLibraryResults.hashCode); _$hash = $jc(_$hash, element.hashCode); _$hash = $jf(_$hash); return _$hash; @@ -65,6 +74,7 @@ class _$EnumSourceLibrary extends EnumSourceLibrary { @override String toString() { return (newBuiltValueToStringHelper(r'EnumSourceLibrary') + ..add('parsedLibraryResults', parsedLibraryResults) ..add('element', element)) .toString(); } @@ -74,6 +84,12 @@ class EnumSourceLibraryBuilder implements Builder { _$EnumSourceLibrary? _$v; + ParsedLibraryResults? _parsedLibraryResults; + ParsedLibraryResults? get parsedLibraryResults => + _$this._parsedLibraryResults; + set parsedLibraryResults(ParsedLibraryResults? parsedLibraryResults) => + _$this._parsedLibraryResults = parsedLibraryResults; + LibraryElement? _element; LibraryElement? get element => _$this._element; set element(LibraryElement? element) => _$this._element = element; @@ -83,6 +99,7 @@ class EnumSourceLibraryBuilder EnumSourceLibraryBuilder get _$this { final $v = _$v; if ($v != null) { + _parsedLibraryResults = $v.parsedLibraryResults; _element = $v.element; _$v = null; } @@ -106,6 +123,10 @@ class EnumSourceLibraryBuilder _$EnumSourceLibrary _build() { final _$result = _$v ?? new _$EnumSourceLibrary._( + parsedLibraryResults: BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, + r'EnumSourceLibrary', + 'parsedLibraryResults'), element: BuiltValueNullFieldError.checkNotNull( element, r'EnumSourceLibrary', 'element')); replace(_$result); diff --git a/built_value_generator/lib/src/parsed_library_results.dart b/built_value_generator/lib/src/parsed_library_results.dart new file mode 100644 index 00000000..8464fc9c --- /dev/null +++ b/built_value_generator/lib/src/parsed_library_results.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2021, Google Inc. Please see the AUTHORS file for details. +// All rights reserved. Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/dart/element/element.dart'; + +/// Caches parsed library results across one generation. +/// +/// Substitutes a "throwing mock" if no parsed library is available. +class ParsedLibraryResults { + final Map _results = {}; + + ParsedLibraryResult parsedLibraryResultOrThrowingMock( + LibraryElement element) { + var uri = element.source.uri; + return _results[uri] ??= _parsedLibraryResultOrThrowingMock(element); + } + + ParsedLibraryResult _parsedLibraryResultOrThrowingMock( + LibraryElement element) { + var result = element.session.getParsedLibraryByElement(element); + if (result is ParsedLibraryResult) { + return result; + } + return _ParsedLibraryResultMock(); + } +} + +class _ParsedLibraryResultMock implements ParsedLibraryResult { + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} diff --git a/built_value_generator/lib/src/serializer_source_class.dart b/built_value_generator/lib/src/serializer_source_class.dart index d806b2b5..b89c0e01 100644 --- a/built_value_generator/lib/src/serializer_source_class.dart +++ b/built_value_generator/lib/src/serializer_source_class.dart @@ -9,10 +9,10 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; -import 'package:built_value_generator/src/analyzer.dart'; import 'package:built_value_generator/src/enum_source_class.dart'; import 'package:built_value_generator/src/enum_source_field.dart'; import 'package:built_value_generator/src/fields.dart' show collectFields; +import 'package:built_value_generator/src/parsed_library_results.dart'; import 'package:built_value_generator/src/serializer_source_field.dart'; import 'package:built_value_generator/src/strings.dart'; import 'package:built_value_generator/src/value_source_class.dart'; @@ -23,12 +23,15 @@ part 'serializer_source_class.g.dart'; abstract class SerializerSourceClass implements Built { + ParsedLibraryResults get parsedLibraryResults; InterfaceElement get element; ClassElement? get builderElement; - factory SerializerSourceClass(InterfaceElement element) => + factory SerializerSourceClass(ParsedLibraryResults parsedLibraryResults, + InterfaceElement element) => _$SerializerSourceClass._( + parsedLibraryResults: parsedLibraryResults, element: element, builderElement: element.library.getClass(element.displayName + 'Builder')); @@ -37,11 +40,12 @@ abstract class SerializerSourceClass @memoized ParsedLibraryResult get parsedLibrary => - parsedLibraryResultOrThrowingMock(element.library); + parsedLibraryResults.parsedLibraryResultOrThrowingMock(element.library); // TODO(davidmorgan): share common code in a nicer way. @memoized - BuiltValue get builtValueSettings => ValueSourceClass(element).settings; + BuiltValue get builtValueSettings => + ValueSourceClass(parsedLibraryResults, element).settings; @memoized bool get hasBuilder => builderElement != null; @@ -73,7 +77,7 @@ abstract class SerializerSourceClass // TODO(davidmorgan): share common code in a nicer way. @memoized BuiltValueEnum get enumClassSettings => - EnumSourceClass(parsedLibrary, element).settings; + EnumSourceClass(parsedLibraryResults, element).settings; @memoized String get name => element.name; @@ -154,7 +158,7 @@ abstract class SerializerSourceClass for (var fieldElement in collectFields(element)) { final builderFieldElement = builderElement?.getField(fieldElement.displayName); - final sourceField = SerializerSourceField( + final sourceField = SerializerSourceField(parsedLibraryResults, builtValueSettings, parsedLibrary, fieldElement, builderFieldElement); if (sourceField.isSerializable) { result.add(sourceField); @@ -198,7 +202,8 @@ abstract class SerializerSourceClass // Type is not fully specified, ignore. if (typeElement is! ClassElement) continue; - final sourceClass = SerializerSourceClass(typeElement); + final sourceClass = + SerializerSourceClass(parsedLibraryResults, typeElement); if (sourceClass != this && !result.build().contains(sourceClass) && @@ -209,7 +214,8 @@ abstract class SerializerSourceClass } } - final sourceClass = SerializerSourceClass(fieldTypeElement); + final sourceClass = + SerializerSourceClass(parsedLibraryResults, fieldTypeElement); if (sourceClass != this && !result.build().contains(sourceClass) && sourceClass.isSerializable) { diff --git a/built_value_generator/lib/src/serializer_source_class.g.dart b/built_value_generator/lib/src/serializer_source_class.g.dart index 83d4f5ca..1a91b8c6 100644 --- a/built_value_generator/lib/src/serializer_source_class.g.dart +++ b/built_value_generator/lib/src/serializer_source_class.g.dart @@ -7,6 +7,8 @@ part of 'serializer_source_class.dart'; // ************************************************************************** class _$SerializerSourceClass extends SerializerSourceClass { + @override + final ParsedLibraryResults parsedLibraryResults; @override final InterfaceElement element; @override @@ -37,8 +39,13 @@ class _$SerializerSourceClass extends SerializerSourceClass { [void Function(SerializerSourceClassBuilder)? updates]) => (new SerializerSourceClassBuilder()..update(updates))._build(); - _$SerializerSourceClass._({required this.element, this.builderElement}) + _$SerializerSourceClass._( + {required this.parsedLibraryResults, + required this.element, + this.builderElement}) : super._() { + BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, r'SerializerSourceClass', 'parsedLibraryResults'); BuiltValueNullFieldError.checkNotNull( element, r'SerializerSourceClass', 'element'); } @@ -132,6 +139,7 @@ class _$SerializerSourceClass extends SerializerSourceClass { bool operator ==(Object other) { if (identical(other, this)) return true; return other is SerializerSourceClass && + parsedLibraryResults == other.parsedLibraryResults && element == other.element && builderElement == other.builderElement; } @@ -139,6 +147,7 @@ class _$SerializerSourceClass extends SerializerSourceClass { @override int get hashCode { var _$hash = 0; + _$hash = $jc(_$hash, parsedLibraryResults.hashCode); _$hash = $jc(_$hash, element.hashCode); _$hash = $jc(_$hash, builderElement.hashCode); _$hash = $jf(_$hash); @@ -148,6 +157,7 @@ class _$SerializerSourceClass extends SerializerSourceClass { @override String toString() { return (newBuiltValueToStringHelper(r'SerializerSourceClass') + ..add('parsedLibraryResults', parsedLibraryResults) ..add('element', element) ..add('builderElement', builderElement)) .toString(); @@ -158,6 +168,12 @@ class SerializerSourceClassBuilder implements Builder { _$SerializerSourceClass? _$v; + ParsedLibraryResults? _parsedLibraryResults; + ParsedLibraryResults? get parsedLibraryResults => + _$this._parsedLibraryResults; + set parsedLibraryResults(ParsedLibraryResults? parsedLibraryResults) => + _$this._parsedLibraryResults = parsedLibraryResults; + InterfaceElement? _element; InterfaceElement? get element => _$this._element; set element(InterfaceElement? element) => _$this._element = element; @@ -172,6 +188,7 @@ class SerializerSourceClassBuilder SerializerSourceClassBuilder get _$this { final $v = _$v; if ($v != null) { + _parsedLibraryResults = $v.parsedLibraryResults; _element = $v.element; _builderElement = $v.builderElement; _$v = null; @@ -196,6 +213,10 @@ class SerializerSourceClassBuilder _$SerializerSourceClass _build() { final _$result = _$v ?? new _$SerializerSourceClass._( + parsedLibraryResults: BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, + r'SerializerSourceClass', + 'parsedLibraryResults'), element: BuiltValueNullFieldError.checkNotNull( element, r'SerializerSourceClass', 'element'), builderElement: builderElement); diff --git a/built_value_generator/lib/src/serializer_source_field.dart b/built_value_generator/lib/src/serializer_source_field.dart index 2739f207..340132a0 100644 --- a/built_value_generator/lib/src/serializer_source_field.dart +++ b/built_value_generator/lib/src/serializer_source_field.dart @@ -15,6 +15,7 @@ import 'package:built_value_generator/src/dart_types.dart'; import 'package:built_value_generator/src/field_mixin.dart'; import 'package:built_value_generator/src/metadata.dart' show metadataToStringValue; +import 'package:built_value_generator/src/parsed_library_results.dart'; import 'package:built_value_generator/src/strings.dart'; part 'serializer_source_field.g.dart'; @@ -30,6 +31,7 @@ abstract class SerializerSourceField 'BuiltSet': 'SetBuilder', 'BuiltSetMultimap': 'SetMultimapBuilder', }); + ParsedLibraryResults get parsedLibraryResults; BuiltValue get settings; @override ParsedLibraryResult get parsedLibrary; @@ -38,11 +40,13 @@ abstract class SerializerSourceField FieldElement? get builderElement; factory SerializerSourceField( + ParsedLibraryResults parsedLibraryResults, BuiltValue settings, ParsedLibraryResult parsedLibrary, FieldElement element, FieldElement? builderElement) => _$SerializerSourceField._( + parsedLibraryResults: parsedLibraryResults, settings: settings, parsedLibrary: parsedLibrary, element: element, @@ -153,7 +157,8 @@ abstract class SerializerSourceField ? DartTypes.getName(element.getter!.returnType) != DartTypes.getName(builderElement!.getter!.returnType) : (builtValueField.nestedBuilder ?? settings.nestedBuilders) && - DartTypes.needsNestedBuilder(element.getter!.returnType); + DartTypes.needsNestedBuilder( + parsedLibraryResults, element.getter!.returnType); } @memoized diff --git a/built_value_generator/lib/src/serializer_source_field.g.dart b/built_value_generator/lib/src/serializer_source_field.g.dart index eae7d0b0..dacfc80e 100644 --- a/built_value_generator/lib/src/serializer_source_field.g.dart +++ b/built_value_generator/lib/src/serializer_source_field.g.dart @@ -7,6 +7,8 @@ part of 'serializer_source_field.dart'; // ************************************************************************** class _$SerializerSourceField extends SerializerSourceField { + @override + final ParsedLibraryResults parsedLibraryResults; @override final BuiltValue settings; @override @@ -39,11 +41,14 @@ class _$SerializerSourceField extends SerializerSourceField { (new SerializerSourceFieldBuilder()..update(updates))._build(); _$SerializerSourceField._( - {required this.settings, + {required this.parsedLibraryResults, + required this.settings, required this.parsedLibrary, required this.element, this.builderElement}) : super._() { + BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, r'SerializerSourceField', 'parsedLibraryResults'); BuiltValueNullFieldError.checkNotNull( settings, r'SerializerSourceField', 'settings'); BuiltValueNullFieldError.checkNotNull( @@ -130,6 +135,7 @@ class _$SerializerSourceField extends SerializerSourceField { bool operator ==(Object other) { if (identical(other, this)) return true; return other is SerializerSourceField && + parsedLibraryResults == other.parsedLibraryResults && settings == other.settings && parsedLibrary == other.parsedLibrary && element == other.element && @@ -139,6 +145,7 @@ class _$SerializerSourceField extends SerializerSourceField { @override int get hashCode { var _$hash = 0; + _$hash = $jc(_$hash, parsedLibraryResults.hashCode); _$hash = $jc(_$hash, settings.hashCode); _$hash = $jc(_$hash, parsedLibrary.hashCode); _$hash = $jc(_$hash, element.hashCode); @@ -150,6 +157,7 @@ class _$SerializerSourceField extends SerializerSourceField { @override String toString() { return (newBuiltValueToStringHelper(r'SerializerSourceField') + ..add('parsedLibraryResults', parsedLibraryResults) ..add('settings', settings) ..add('parsedLibrary', parsedLibrary) ..add('element', element) @@ -162,6 +170,12 @@ class SerializerSourceFieldBuilder implements Builder { _$SerializerSourceField? _$v; + ParsedLibraryResults? _parsedLibraryResults; + ParsedLibraryResults? get parsedLibraryResults => + _$this._parsedLibraryResults; + set parsedLibraryResults(ParsedLibraryResults? parsedLibraryResults) => + _$this._parsedLibraryResults = parsedLibraryResults; + BuiltValue? _settings; BuiltValue? get settings => _$this._settings; set settings(BuiltValue? settings) => _$this._settings = settings; @@ -185,6 +199,7 @@ class SerializerSourceFieldBuilder SerializerSourceFieldBuilder get _$this { final $v = _$v; if ($v != null) { + _parsedLibraryResults = $v.parsedLibraryResults; _settings = $v.settings; _parsedLibrary = $v.parsedLibrary; _element = $v.element; @@ -211,6 +226,10 @@ class SerializerSourceFieldBuilder _$SerializerSourceField _build() { final _$result = _$v ?? new _$SerializerSourceField._( + parsedLibraryResults: BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, + r'SerializerSourceField', + 'parsedLibraryResults'), settings: BuiltValueNullFieldError.checkNotNull( settings, r'SerializerSourceField', 'settings'), parsedLibrary: BuiltValueNullFieldError.checkNotNull( diff --git a/built_value_generator/lib/src/serializer_source_library.dart b/built_value_generator/lib/src/serializer_source_library.dart index e1da72b9..e74f88a2 100644 --- a/built_value_generator/lib/src/serializer_source_library.dart +++ b/built_value_generator/lib/src/serializer_source_library.dart @@ -8,8 +8,8 @@ import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; -import 'package:built_value_generator/src/analyzer.dart'; import 'package:built_value_generator/src/library_elements.dart'; +import 'package:built_value_generator/src/parsed_library_results.dart'; import 'package:built_value_generator/src/serializer_source_class.dart'; import 'package:source_gen/source_gen.dart'; @@ -19,15 +19,18 @@ part 'serializer_source_library.g.dart'; abstract class SerializerSourceLibrary implements Built { + ParsedLibraryResults get parsedLibraryResults; LibraryElement get element; - factory SerializerSourceLibrary(LibraryElement element) => - _$SerializerSourceLibrary._(element: element); + factory SerializerSourceLibrary( + ParsedLibraryResults parsedLibraryResults, LibraryElement element) => + _$SerializerSourceLibrary._( + parsedLibraryResults: parsedLibraryResults, element: element); SerializerSourceLibrary._(); @memoized ParsedLibraryResult get parsedLibrary => - parsedLibraryResultOrThrowingMock(element.library); + parsedLibraryResults.parsedLibraryResultOrThrowingMock(element.library); @memoized bool get hasSerializers => serializersForAnnotations.isNotEmpty; @@ -90,7 +93,8 @@ abstract class SerializerSourceLibrary var result = SetBuilder(); var classElements = LibraryElements.getClassElements(element); for (var classElement in classElements) { - final sourceClass = SerializerSourceClass(classElement); + final sourceClass = + SerializerSourceClass(parsedLibraryResults, classElement); if (sourceClass.isSerializable) { result.add(sourceClass); } @@ -121,8 +125,8 @@ abstract class SerializerSourceLibrary result.addValues( field, - types.map((type) => - SerializerSourceClass(type!.element as InterfaceElement))); + types.map((type) => SerializerSourceClass( + parsedLibraryResults, type!.element as InterfaceElement))); } return result.build(); } diff --git a/built_value_generator/lib/src/serializer_source_library.g.dart b/built_value_generator/lib/src/serializer_source_library.g.dart index 62bc1c55..61276db8 100644 --- a/built_value_generator/lib/src/serializer_source_library.g.dart +++ b/built_value_generator/lib/src/serializer_source_library.g.dart @@ -7,6 +7,8 @@ part of 'serializer_source_library.dart'; // ************************************************************************** class _$SerializerSourceLibrary extends SerializerSourceLibrary { + @override + final ParsedLibraryResults parsedLibraryResults; @override final LibraryElement element; ParsedLibraryResult? __parsedLibrary; @@ -22,7 +24,11 @@ class _$SerializerSourceLibrary extends SerializerSourceLibrary { [void Function(SerializerSourceLibraryBuilder)? updates]) => (new SerializerSourceLibraryBuilder()..update(updates))._build(); - _$SerializerSourceLibrary._({required this.element}) : super._() { + _$SerializerSourceLibrary._( + {required this.parsedLibraryResults, required this.element}) + : super._() { + BuiltValueNullFieldError.checkNotNull(parsedLibraryResults, + r'SerializerSourceLibrary', 'parsedLibraryResults'); BuiltValueNullFieldError.checkNotNull( element, r'SerializerSourceLibrary', 'element'); } @@ -67,12 +73,15 @@ class _$SerializerSourceLibrary extends SerializerSourceLibrary { @override bool operator ==(Object other) { if (identical(other, this)) return true; - return other is SerializerSourceLibrary && element == other.element; + return other is SerializerSourceLibrary && + parsedLibraryResults == other.parsedLibraryResults && + element == other.element; } @override int get hashCode { var _$hash = 0; + _$hash = $jc(_$hash, parsedLibraryResults.hashCode); _$hash = $jc(_$hash, element.hashCode); _$hash = $jf(_$hash); return _$hash; @@ -81,6 +90,7 @@ class _$SerializerSourceLibrary extends SerializerSourceLibrary { @override String toString() { return (newBuiltValueToStringHelper(r'SerializerSourceLibrary') + ..add('parsedLibraryResults', parsedLibraryResults) ..add('element', element)) .toString(); } @@ -91,6 +101,12 @@ class SerializerSourceLibraryBuilder Builder { _$SerializerSourceLibrary? _$v; + ParsedLibraryResults? _parsedLibraryResults; + ParsedLibraryResults? get parsedLibraryResults => + _$this._parsedLibraryResults; + set parsedLibraryResults(ParsedLibraryResults? parsedLibraryResults) => + _$this._parsedLibraryResults = parsedLibraryResults; + LibraryElement? _element; LibraryElement? get element => _$this._element; set element(LibraryElement? element) => _$this._element = element; @@ -100,6 +116,7 @@ class SerializerSourceLibraryBuilder SerializerSourceLibraryBuilder get _$this { final $v = _$v; if ($v != null) { + _parsedLibraryResults = $v.parsedLibraryResults; _element = $v.element; _$v = null; } @@ -123,6 +140,10 @@ class SerializerSourceLibraryBuilder _$SerializerSourceLibrary _build() { final _$result = _$v ?? new _$SerializerSourceLibrary._( + parsedLibraryResults: BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, + r'SerializerSourceLibrary', + 'parsedLibraryResults'), element: BuiltValueNullFieldError.checkNotNull( element, r'SerializerSourceLibrary', 'element')); replace(_$result); diff --git a/built_value_generator/lib/src/value_source_class.dart b/built_value_generator/lib/src/value_source_class.dart index eb82a18f..12f9a0b5 100644 --- a/built_value_generator/lib/src/value_source_class.dart +++ b/built_value_generator/lib/src/value_source_class.dart @@ -11,10 +11,10 @@ import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; -import 'package:built_value_generator/src/analyzer.dart'; import 'package:built_value_generator/src/fixes.dart'; import 'package:built_value_generator/src/memoized_getter.dart'; import 'package:built_value_generator/src/metadata.dart'; +import 'package:built_value_generator/src/parsed_library_results.dart'; import 'package:built_value_generator/src/strings.dart'; import 'package:built_value_generator/src/value_source_field.dart'; import 'package:collection/collection.dart'; @@ -32,15 +32,18 @@ const String _importWithDoubleQuotes = abstract class ValueSourceClass implements Built { + ParsedLibraryResults get parsedLibraryResults; InterfaceElement get element; - factory ValueSourceClass(InterfaceElement element) => - _$ValueSourceClass._(element: element); + factory ValueSourceClass(ParsedLibraryResults parsedLibraryResults, + InterfaceElement element) => + _$ValueSourceClass._( + parsedLibraryResults: parsedLibraryResults, element: element); ValueSourceClass._(); @memoized ParsedLibraryResult get parsedLibrary => - parsedLibraryResultOrThrowingMock(element.library); + parsedLibraryResults.parsedLibraryResultOrThrowingMock(element.library); @memoized String get name => element.displayName; @@ -221,7 +224,7 @@ abstract class ValueSourceClass @memoized BuiltList get fields => ValueSourceField.fromClassElements( - settings, parsedLibrary, element, builderElement); + parsedLibraryResults, settings, parsedLibrary, element, builderElement); @memoized String get source => diff --git a/built_value_generator/lib/src/value_source_class.g.dart b/built_value_generator/lib/src/value_source_class.g.dart index b1448657..8ed2c506 100644 --- a/built_value_generator/lib/src/value_source_class.g.dart +++ b/built_value_generator/lib/src/value_source_class.g.dart @@ -7,6 +7,8 @@ part of 'value_source_class.dart'; // ************************************************************************** class _$ValueSourceClass extends ValueSourceClass { + @override + final ParsedLibraryResults parsedLibraryResults; @override final InterfaceElement element; ParsedLibraryResult? __parsedLibrary; @@ -54,7 +56,11 @@ class _$ValueSourceClass extends ValueSourceClass { [void Function(ValueSourceClassBuilder)? updates]) => (new ValueSourceClassBuilder()..update(updates))._build(); - _$ValueSourceClass._({required this.element}) : super._() { + _$ValueSourceClass._( + {required this.parsedLibraryResults, required this.element}) + : super._() { + BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, r'ValueSourceClass', 'parsedLibraryResults'); BuiltValueNullFieldError.checkNotNull( element, r'ValueSourceClass', 'element'); } @@ -222,12 +228,15 @@ class _$ValueSourceClass extends ValueSourceClass { @override bool operator ==(Object other) { if (identical(other, this)) return true; - return other is ValueSourceClass && element == other.element; + return other is ValueSourceClass && + parsedLibraryResults == other.parsedLibraryResults && + element == other.element; } @override int get hashCode { var _$hash = 0; + _$hash = $jc(_$hash, parsedLibraryResults.hashCode); _$hash = $jc(_$hash, element.hashCode); _$hash = $jf(_$hash); return _$hash; @@ -236,6 +245,7 @@ class _$ValueSourceClass extends ValueSourceClass { @override String toString() { return (newBuiltValueToStringHelper(r'ValueSourceClass') + ..add('parsedLibraryResults', parsedLibraryResults) ..add('element', element)) .toString(); } @@ -245,6 +255,12 @@ class ValueSourceClassBuilder implements Builder { _$ValueSourceClass? _$v; + ParsedLibraryResults? _parsedLibraryResults; + ParsedLibraryResults? get parsedLibraryResults => + _$this._parsedLibraryResults; + set parsedLibraryResults(ParsedLibraryResults? parsedLibraryResults) => + _$this._parsedLibraryResults = parsedLibraryResults; + InterfaceElement? _element; InterfaceElement? get element => _$this._element; set element(InterfaceElement? element) => _$this._element = element; @@ -254,6 +270,7 @@ class ValueSourceClassBuilder ValueSourceClassBuilder get _$this { final $v = _$v; if ($v != null) { + _parsedLibraryResults = $v.parsedLibraryResults; _element = $v.element; _$v = null; } @@ -277,6 +294,10 @@ class ValueSourceClassBuilder _$ValueSourceClass _build() { final _$result = _$v ?? new _$ValueSourceClass._( + parsedLibraryResults: BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, + r'ValueSourceClass', + 'parsedLibraryResults'), element: BuiltValueNullFieldError.checkNotNull( element, r'ValueSourceClass', 'element')); replace(_$result); diff --git a/built_value_generator/lib/src/value_source_field.dart b/built_value_generator/lib/src/value_source_field.dart index dab30aff..6763fde0 100644 --- a/built_value_generator/lib/src/value_source_field.dart +++ b/built_value_generator/lib/src/value_source_field.dart @@ -17,6 +17,7 @@ import 'package:built_value_generator/src/fields.dart' show collectFields; import 'package:built_value_generator/src/fixes.dart'; import 'package:built_value_generator/src/metadata.dart' show metadataToStringValue; +import 'package:built_value_generator/src/parsed_library_results.dart'; part 'value_source_field.g.dart'; @@ -31,6 +32,7 @@ const _suggestedTypes = { abstract class ValueSourceField with FieldMixin implements Built { + ParsedLibraryResults get parsedLibraryResults; BuiltValue get settings; @override ParsedLibraryResult get parsedLibrary; @@ -39,11 +41,13 @@ abstract class ValueSourceField FieldElement? get builderElement; factory ValueSourceField( + ParsedLibraryResults parsedLibraryResults, BuiltValue settings, ParsedLibraryResult parsedLibrary, FieldElement element, FieldElement? builderElement) => _$ValueSourceField._( + parsedLibraryResults: parsedLibraryResults, settings: settings, parsedLibrary: parsedLibrary, element: element, @@ -237,14 +241,15 @@ abstract class ValueSourceField String? typeInBuilder(CompilationUnitElement? compilationUnit) => builderFieldExists ? buildElementType - : _toBuilderType(element.getter!.returnType, + : _toBuilderType(parsedLibraryResults, element.getter!.returnType, typeInCompilationUnit(compilationUnit)); @memoized bool get isNestedBuilder => builderFieldExists ? typeInBuilder(null)?.contains('Builder') ?? false : (builtValueField.nestedBuilder ?? settings.nestedBuilders) && - DartTypes.needsNestedBuilder(element.getter!.returnType); + DartTypes.needsNestedBuilder( + parsedLibraryResults, element.getter!.returnType); @memoized bool get isAutoCreateNestedBuilder => @@ -252,6 +257,7 @@ abstract class ValueSourceField settings.autoCreateNestedBuilders; static BuiltList fromClassElements( + ParsedLibraryResults parsedLibraryResults, BuiltValue settings, ParsedLibraryResult parsedLibrary, InterfaceElement classElement, @@ -263,20 +269,21 @@ abstract class ValueSourceField field.getter != null && (field.getter!.isAbstract || field.getter!.isSynthetic)) { final builderField = builderClassElement?.getField(field.name); - result.add( - ValueSourceField(settings, parsedLibrary, field, builderField)); + result.add(ValueSourceField(parsedLibraryResults, settings, + parsedLibrary, field, builderField)); } } return result.build(); } - static String? _toBuilderType(DartType type, String displayName) { + static String? _toBuilderType(ParsedLibraryResults parsedLibraryResults, + DartType type, String displayName) { if (DartTypes.isBuiltCollection(type)) { return displayName .replaceFirst('Built', '') .replaceFirst('<', 'Builder<'); - } else if (DartTypes.isInstantiableBuiltValue(type)) { + } else if (DartTypes.isInstantiableBuiltValue(parsedLibraryResults, type)) { return displayName.contains('<') ? displayName.replaceFirst('<', 'Builder<') : '${displayName}Builder'; @@ -321,7 +328,8 @@ abstract class ValueSourceField if (builderFieldExists) { var builderElementTypeOrNull = buildElementType; if (builderElementTypeIsNullable) builderElementTypeOrNull += '?'; - final builderType = _toBuilderType(element.type, type); + final builderType = + _toBuilderType(parsedLibraryResults, element.type, type); if (builderElementTypeOrNull != type + '?' && (builderType == null || (builderElementTypeOrNull != builderType && diff --git a/built_value_generator/lib/src/value_source_field.g.dart b/built_value_generator/lib/src/value_source_field.g.dart index fdb2218f..b6c502b6 100644 --- a/built_value_generator/lib/src/value_source_field.g.dart +++ b/built_value_generator/lib/src/value_source_field.g.dart @@ -7,6 +7,8 @@ part of 'value_source_field.dart'; // ************************************************************************** class _$ValueSourceField extends ValueSourceField { + @override + final ParsedLibraryResults parsedLibraryResults; @override final BuiltValue settings; @override @@ -39,11 +41,14 @@ class _$ValueSourceField extends ValueSourceField { (new ValueSourceFieldBuilder()..update(updates))._build(); _$ValueSourceField._( - {required this.settings, + {required this.parsedLibraryResults, + required this.settings, required this.parsedLibrary, required this.element, this.builderElement}) : super._() { + BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, r'ValueSourceField', 'parsedLibraryResults'); BuiltValueNullFieldError.checkNotNull( settings, r'ValueSourceField', 'settings'); BuiltValueNullFieldError.checkNotNull( @@ -127,6 +132,7 @@ class _$ValueSourceField extends ValueSourceField { bool operator ==(Object other) { if (identical(other, this)) return true; return other is ValueSourceField && + parsedLibraryResults == other.parsedLibraryResults && settings == other.settings && parsedLibrary == other.parsedLibrary && element == other.element && @@ -136,6 +142,7 @@ class _$ValueSourceField extends ValueSourceField { @override int get hashCode { var _$hash = 0; + _$hash = $jc(_$hash, parsedLibraryResults.hashCode); _$hash = $jc(_$hash, settings.hashCode); _$hash = $jc(_$hash, parsedLibrary.hashCode); _$hash = $jc(_$hash, element.hashCode); @@ -147,6 +154,7 @@ class _$ValueSourceField extends ValueSourceField { @override String toString() { return (newBuiltValueToStringHelper(r'ValueSourceField') + ..add('parsedLibraryResults', parsedLibraryResults) ..add('settings', settings) ..add('parsedLibrary', parsedLibrary) ..add('element', element) @@ -159,6 +167,12 @@ class ValueSourceFieldBuilder implements Builder { _$ValueSourceField? _$v; + ParsedLibraryResults? _parsedLibraryResults; + ParsedLibraryResults? get parsedLibraryResults => + _$this._parsedLibraryResults; + set parsedLibraryResults(ParsedLibraryResults? parsedLibraryResults) => + _$this._parsedLibraryResults = parsedLibraryResults; + BuiltValue? _settings; BuiltValue? get settings => _$this._settings; set settings(BuiltValue? settings) => _$this._settings = settings; @@ -182,6 +196,7 @@ class ValueSourceFieldBuilder ValueSourceFieldBuilder get _$this { final $v = _$v; if ($v != null) { + _parsedLibraryResults = $v.parsedLibraryResults; _settings = $v.settings; _parsedLibrary = $v.parsedLibrary; _element = $v.element; @@ -208,6 +223,10 @@ class ValueSourceFieldBuilder _$ValueSourceField _build() { final _$result = _$v ?? new _$ValueSourceField._( + parsedLibraryResults: BuiltValueNullFieldError.checkNotNull( + parsedLibraryResults, + r'ValueSourceField', + 'parsedLibraryResults'), settings: BuiltValueNullFieldError.checkNotNull( settings, r'ValueSourceField', 'settings'), parsedLibrary: BuiltValueNullFieldError.checkNotNull( diff --git a/tool/presubmit b/tool/presubmit index 6fcbf56b..8a2eafd6 100755 --- a/tool/presubmit +++ b/tool/presubmit @@ -33,7 +33,7 @@ for directory in $directories; do rm -rf .dart_tool/build/ grep -q build_runner pubspec.yaml && \ - dart pub run build_runner build \ + dart run build_runner build \ --delete-conflicting-outputs \ --fail-on-severe done @@ -56,5 +56,28 @@ for directory in $directories; do echo cd "$parent_directory/$directory" - dart pub run test + dart run test done + + +echo "*** Preparing to benchmark build..." +cd "$parent_directory/end_to_end_test" +cat << 'EOF' > lib/many_values.dart +import 'package:built_value/built_value.dart'; +part 'many_values.g.dart'; +EOF +dart run build_runner build + +for n in $(seq 1 2500); do + cat << 'EOF' | sed -e "s#1#$n#g" >> lib/many_values.dart + abstract class Value1 implements Built { + factory Value1([void Function(Value1Builder) updates]) = _$Value1; + Value1._(); + } +EOF +done +echo "*** Benchmarking build, should be ~30s..." +dart run build_runner build + +rm "$parent_directory/end_to_end_test/lib/many_values.dart" +rm "$parent_directory/end_to_end_test/lib/many_values.g.dart"