Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache parsed library results. #1307

Merged
merged 1 commit into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

# 8.9.2

- Improve build performance when there are lots of `built_value` classes.

# 8.9.1

- Fix for new warning about `operator==` param type.
Expand Down
16 changes: 11 additions & 5 deletions built_value_generator/lib/built_value_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -18,14 +19,16 @@ class BuiltValueGenerator extends Generator {

@override
Future<String?> 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;
while (true) {
try {
libraryElement = await buildStep.resolver.libraryFor(
await buildStep.resolver.assetIdForElement(library.element));
libraryElement.session.getParsedLibraryByElement(libraryElement);
parsedLibraryResults.parsedLibraryResultOrThrowingMock(libraryElement);
break;
} catch (_) {
++attempts;
Expand All @@ -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());
Expand All @@ -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);
Expand Down
19 changes: 0 additions & 19 deletions built_value_generator/lib/src/analyzer.dart

This file was deleted.

14 changes: 10 additions & 4 deletions built_value_generator/lib/src/dart_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> _builtCollectionNames = BuiltSet<String>([
Expand All @@ -17,13 +18,18 @@ BuiltSet<String> _builtCollectionNames = BuiltSet<String>([
]);

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) =>
Expand Down
13 changes: 8 additions & 5 deletions built_value_generator/lib/src/enum_source_class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -21,16 +21,19 @@ part 'enum_source_class.g.dart';

abstract class EnumSourceClass
implements Built<EnumSourceClass, EnumSourceClassBuilder> {
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;
Expand Down
25 changes: 23 additions & 2 deletions built_value_generator/lib/src/enum_source_class.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions built_value_generator/lib/src/enum_source_library.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<EnumSourceLibrary, EnumSourceLibraryBuilder> {
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;
Expand All @@ -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();
Expand Down
25 changes: 23 additions & 2 deletions built_value_generator/lib/src/enum_source_library.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions built_value_generator/lib/src/parsed_library_results.dart
Original file line number Diff line number Diff line change
@@ -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<Uri, ParsedLibraryResult> _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);
}
Loading