From ac1837fdd1ba6eed236082c88537fdb8c619b1f4 Mon Sep 17 00:00:00 2001 From: Matthew Berry Date: Sun, 9 Jun 2024 12:59:49 -0700 Subject: [PATCH] Revive to the object's `variableElement` if available (#713) Variables have been tracked on DartObject since https://dart.googlesource.com/sdk/+/54b7f4b72a1701f8f9a0334c94ce6f59732bd261. This change uses the variable in the reviver if it exists. I believe the existing tests in https://github.com/dart-lang/source_gen/blob/master/source_gen/test/constants_test.dart already cover this, but lmk if you'd like any additional tests --- source_gen/CHANGELOG.md | 3 ++- source_gen/lib/src/constants/revive.dart | 15 +++++++++++++++ source_gen/test/constants_test.dart | 11 +++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/source_gen/CHANGELOG.md b/source_gen/CHANGELOG.md index 94e5bd0d..02a3ff3e 100644 --- a/source_gen/CHANGELOG.md +++ b/source_gen/CHANGELOG.md @@ -3,8 +3,9 @@ - Document deduplication behavior for the output of `GeneratorForAnnotation.generateForAnnotatedElement`. - Support all the glob quotes. -- Require Dart 3.4.0 +- Revive to the object's `variableElement` if available - Require `analyzer: ^6.4.0` +- Require Dart 3.4.0 ## 1.5.0 diff --git a/source_gen/lib/src/constants/revive.dart b/source_gen/lib/src/constants/revive.dart index 63b44e43..56a810ca 100644 --- a/source_gen/lib/src/constants/revive.dart +++ b/source_gen/lib/src/constants/revive.dart @@ -20,6 +20,21 @@ import '../utils.dart'; /// Dart source code (such as referencing private constructors). It is up to the /// build tool(s) using this library to surface error messages to the user. Revivable reviveInstance(DartObject object, [LibraryElement? origin]) { + final variableElement = object.variable; + if (variableElement != null && + variableElement.isConst && + variableElement.isPublic) { + final url = Uri.parse(urlOfElement(variableElement)).removeFragment(); + if (variableElement.enclosingElement + case final TypeDefiningElement enclosingElement?) { + return Revivable._( + source: url, + accessor: '${enclosingElement.name}.${variableElement.name}', + ); + } + return Revivable._(source: url, accessor: variableElement.name); + } + final objectType = object.type; Element? element = objectType!.alias?.element; if (element == null) { diff --git a/source_gen/test/constants_test.dart b/source_gen/test/constants_test.dart index fe97e07c..0335efe9 100644 --- a/source_gen/test/constants_test.dart +++ b/source_gen/test/constants_test.dart @@ -227,6 +227,7 @@ void main() { @_privateField @Wrapper(_privateFunction) @ProcessStartMode.normal + @ExtensionTypeWithStaticField.staticField class Example {} class Int64Like implements Int64LikeBase{ @@ -296,6 +297,10 @@ void main() { } void _privateFunction() {} + + extension type const ExtensionTypeWithStaticField._(int _) { + static const staticField = ExtensionTypeWithStaticField._(1); + } ''', (resolver) async => (await resolver.findLibraryByName('test_lib'))!, ); @@ -393,5 +398,11 @@ void main() { expect(staticFieldWithPrivateImpl.isPrivate, isFalse); expect(staticFieldWithPrivateImpl.source.fragment, isEmpty); }); + + test('should decode static fields on extension types', () { + final fieldOnly = constants[14].revive(); + expect(fieldOnly.source.fragment, isEmpty); + expect(fieldOnly.accessor, 'ExtensionTypeWithStaticField.staticField'); + }); }); }