diff --git a/packages/go_router_builder/CHANGELOG.md b/packages/go_router_builder/CHANGELOG.md index 74d7ed7ce1d..1f8247aa6e3 100644 --- a/packages/go_router_builder/CHANGELOG.md +++ b/packages/go_router_builder/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 4.1.2 +* Updates supported analyzer versions to 8.x or 9.x. * Updates minimum supported SDK version to Flutter 3.32/Dart 3.8. ## 4.1.1 diff --git a/packages/go_router_builder/lib/src/go_router_generator.dart b/packages/go_router_builder/lib/src/go_router_generator.dart index 6019742f47e..80fb3ab93bb 100644 --- a/packages/go_router_builder/lib/src/go_router_generator.dart +++ b/packages/go_router_builder/lib/src/go_router_generator.dart @@ -4,7 +4,7 @@ import 'dart:async'; -import 'package:analyzer/dart/element/element2.dart'; +import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; @@ -76,7 +76,7 @@ ${getters.map((String e) => "$e,").join('\n')} } InfoIterable _generateForAnnotatedElement( - Element2 element, + Element element, ConstantReader annotation, ) { final String typedAnnotation = withoutNullability( @@ -87,7 +87,7 @@ ${getters.map((String e) => "$e,").join('\n')} typedAnnotation.indexOf('<'), ); final String routeData = _annotations[type]!; - if (element is! ClassElement2) { + if (element is! ClassElement) { throw InvalidGenerationSourceError( 'The @$type annotation can only be applied to classes.', element: element, diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart index 84ef2a624bb..6783e5eea70 100644 --- a/packages/go_router_builder/lib/src/route_config.dart +++ b/packages/go_router_builder/lib/src/route_config.dart @@ -6,7 +6,7 @@ import 'dart:collection'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/constant/value.dart'; -import 'package:analyzer/dart/element/element2.dart'; +import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:collection/collection.dart'; @@ -57,14 +57,14 @@ class ShellRouteConfig extends RouteBaseConfig { @override Iterable classDeclarations() { - if (routeDataClass.unnamedConstructor2 == null) { + if (routeDataClass.unnamedConstructor == null) { throw InvalidGenerationSourceError( 'The ShellRouteData "$_className" class must have an unnamed constructor.', element: routeDataClass, ); } - final bool isConst = routeDataClass.unnamedConstructor2!.isConst; + final bool isConst = routeDataClass.unnamedConstructor!.isConst; return [ ''' @@ -116,7 +116,7 @@ class StatefulShellRouteConfig extends RouteBaseConfig { Iterable classDeclarations() => [ ''' extension $_extensionName on $_className { - static $_className _fromState(GoRouterState state) =>${routeDataClass.unnamedConstructor2!.isConst ? ' const' : ''} $_className(); + static $_className _fromState(GoRouterState state) =>${routeDataClass.unnamedConstructor!.isConst ? ' const' : ''} $_className(); } ''', ]; @@ -297,7 +297,7 @@ mixin _GoRouteMixin on RouteBaseConfig { } String _encodeFor(String fieldName) { - final PropertyAccessorElement2? field = _field(fieldName); + final PropertyAccessorElement? field = _field(fieldName); if (field == null) { throw InvalidGenerationSourceError( 'Could not find a field for the path parameter "$fieldName".', @@ -363,8 +363,8 @@ mixin _GoRouteMixin on RouteBaseConfig { ) .toList(); - ConstructorElement2 get _ctor { - final ConstructorElement2? ctor = routeDataClass.unnamedConstructor2; + ConstructorElement get _ctor { + final ConstructorElement? ctor = routeDataClass.unnamedConstructor; if (ctor == null) { throw InvalidGenerationSourceError( @@ -465,7 +465,7 @@ class GoRouteConfig extends RouteBaseConfig with _GoRouteMixin { getNodeDeclaration(routeDataClass) ?.withClause ?.mixinTypes - .any((NamedType e) => e.name2.toString() == _mixinName) ?? + .any((NamedType e) => e.name.toString() == _mixinName) ?? false; if (!hasMixin) { @@ -540,7 +540,7 @@ class RelativeGoRouteConfig extends RouteBaseConfig with _GoRouteMixin { getNodeDeclaration(routeDataClass) ?.withClause ?.mixinTypes - .any((NamedType e) => e.name2.toString() == _mixinName) ?? + .any((NamedType e) => e.name.toString() == _mixinName) ?? false; if (!hasMixin) { @@ -596,7 +596,7 @@ abstract class RouteBaseConfig { /// Creates a new [RouteBaseConfig] represented the annotation data in [reader]. factory RouteBaseConfig.fromAnnotation( ConstantReader reader, - InterfaceElement2 element, + InterfaceElement element, ) { final definition = RouteBaseConfig._fromAnnotation(reader, element, null); @@ -613,7 +613,7 @@ abstract class RouteBaseConfig { factory RouteBaseConfig._fromAnnotation( ConstantReader reader, - InterfaceElement2 element, + InterfaceElement element, RouteBaseConfig? parent, { bool isAncestorRelative = false, }) { @@ -641,8 +641,7 @@ abstract class RouteBaseConfig { } // TODO(kevmoo): validate that this MUST be a subtype of `GoRouteData` - // ignore: experimental_member_use - final InterfaceElement2 classElement = typeParamType.element3; + final InterfaceElement classElement = typeParamType.element; final RouteBaseConfig value; switch (typeName) { @@ -780,7 +779,7 @@ abstract class RouteBaseConfig { final List _children = []; /// The `RouteData` class this class represents. - final InterfaceElement2 routeDataClass; + final InterfaceElement routeDataClass; /// The parent of this route config. final RouteBaseConfig? parent; @@ -793,11 +792,11 @@ abstract class RouteBaseConfig { } static String? _generateParameterGetterCode( - InterfaceElement2 classElement, { + InterfaceElement classElement, { required String parameterName, }) { - final String? fieldDisplayName = classElement.fields2 - .where((FieldElement2 element) { + final String? fieldDisplayName = classElement.fields + .where((FieldElement element) { if (!element.isStatic || element.displayName != parameterName) { return false; } @@ -820,17 +819,17 @@ abstract class RouteBaseConfig { } return true; }) - .map((FieldElement2 e) => e.displayName) + .map((FieldElement e) => e.displayName) .firstOrNull; if (fieldDisplayName != null) { return '${classElement.displayName}.$fieldDisplayName'; } - final String? methodDisplayName = classElement.methods2 - .where((MethodElement2 element) { + final String? methodDisplayName = classElement.methods + .where((MethodElement element) { return element.isStatic && element.displayName == parameterName; }) - .map((MethodElement2 e) => e.displayName) + .map((MethodElement e) => e.displayName) .firstOrNull; if (methodDisplayName != null) { @@ -901,12 +900,12 @@ $routeDataClassName.$dataConvertionFunctionName( '''; } - PropertyAccessorElement2? _field(String name) => - routeDataClass.getGetter2(name); + PropertyAccessorElement? _field(String name) => + routeDataClass.getGetter(name); - List? _fieldMetadata(String name) => routeDataClass.fields2 - .firstWhereOrNull((FieldElement2 element) => element.displayName == name) - ?.metadata2 + List? _fieldMetadata(String name) => routeDataClass.fields + .firstWhereOrNull((FieldElement element) => element.displayName == name) + ?.metadata .annotations; /// The name of `RouteData` subclass this configuration represents. @@ -937,9 +936,8 @@ String _enumMapConst(InterfaceType type) { final buffer = StringBuffer('const ${enumMapName(type)} = {'); - // ignore: experimental_member_use - for (final FieldElement2 enumField in type.element3.fields2.where( - (FieldElement2 element) => element.isEnumConstant, + for (final FieldElement enumField in type.element.fields.where( + (FieldElement element) => element.isEnumConstant, )) { buffer.writeln( '$enumName.${enumField.displayName}: ${escapeDartString(enumField.displayName.kebab)},', diff --git a/packages/go_router_builder/lib/src/type_helpers.dart b/packages/go_router_builder/lib/src/type_helpers.dart index cffec763c01..862b432acd3 100644 --- a/packages/go_router_builder/lib/src/type_helpers.dart +++ b/packages/go_router_builder/lib/src/type_helpers.dart @@ -6,7 +6,7 @@ import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/constant/value.dart'; -import 'package:analyzer/dart/element/element2.dart'; +import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:collection/collection.dart'; import 'package:source_gen/source_gen.dart'; @@ -56,7 +56,7 @@ const List<_TypeHelper> _helpers = <_TypeHelper>[ /// Checks if has a function that converts string to string, such as encode and decode. bool _isStringToStringFunction( - ExecutableElement2? executableElement, + ExecutableElement? executableElement, String name, ) { if (executableElement == null) { @@ -71,9 +71,10 @@ bool _isStringToStringFunction( /// Returns the custom codec for the annotation. String? _getCustomCodec(ElementAnnotation annotation, String name) { - final ExecutableElement2? executableElement = - // ignore: experimental_member_use - annotation.computeConstantValue()?.getField(name)?.toFunctionValue2(); + final ExecutableElement? executableElement = annotation + .computeConstantValue() + ?.getField(name) + ?.toFunctionValue(); if (_isStringToStringFunction(executableElement, name)) { return executableElement!.displayName; } @@ -111,7 +112,7 @@ String decodeParameter( } else { throw InvalidGenerationSourceError( 'The parameter type ' - '`${paramType.getDisplayString(withNullability: false)}` not have a well defined CustomParameterCodec decorator.', + '`${withoutNullability(paramType.getDisplayString())}` not have a well defined CustomParameterCodec decorator.', element: element, ); } @@ -141,7 +142,7 @@ String decodeParameter( /// /// Otherwise, throws an [InvalidGenerationSourceError]. String encodeField( - PropertyAccessorElement2 element, + PropertyAccessorElement element, List? metadata, ) { for (final _TypeHelper helper in _helpers) { @@ -161,7 +162,7 @@ String encodeField( } else { throw InvalidGenerationSourceError( 'The parameter type ' - '`${element.type.getDisplayString(withNullability: false)}` not have a well defined CustomParameterCodec decorator.', + '`${withoutNullability(element.type.getDisplayString())}` not have a well defined CustomParameterCodec decorator.', element: element, ); } @@ -182,18 +183,15 @@ String encodeField( } /// Returns an AstNode type from a InterfaceElement2. -T? getNodeDeclaration(InterfaceElement2 element) { +T? getNodeDeclaration(InterfaceElement element) { final AnalysisSession? session = element.session; if (session == null) { return null; } final parsedLibrary = - // ignore: experimental_member_use - session.getParsedLibraryByElement2(element.library2) - as ParsedLibraryResult; + session.getParsedLibraryByElement(element.library) as ParsedLibraryResult; final FragmentDeclarationResult? declaration = parsedLibrary - // ignore: experimental_member_use .getFragmentDeclaration(element.firstFragment); final AstNode? node = declaration?.node; @@ -698,10 +696,9 @@ class _TypeHelperJson extends _TypeHelperWithHelper { return false; } - final MethodElement2? toJsonMethod = type.lookUpMethod3( + final MethodElement? toJsonMethod = type.lookUpMethod( 'toJson', - // ignore: experimental_member_use - type.element3.library2, + type.element.library, ); if (toJsonMethod == null || !toJsonMethod.isPublic || @@ -715,22 +712,21 @@ class _TypeHelperJson extends _TypeHelperWithHelper { return _matchesType(type.typeArguments.first); } - // ignore: experimental_member_use - final ConstructorElement2? fromJsonMethod = type.element3 - .getNamedConstructor2('fromJson'); + final ConstructorElement? fromJsonMethod = type.element.getNamedConstructor( + 'fromJson', + ); if (fromJsonMethod == null || !fromJsonMethod.isPublic || fromJsonMethod.formalParameters.length != 1 || - fromJsonMethod.formalParameters.first.type.getDisplayString( - withNullability: false, + withoutNullability( + fromJsonMethod.formalParameters.first.type.getDisplayString(), ) != 'Map') { throw InvalidGenerationSourceError( 'The parameter type ' - '`${type.getDisplayString(withNullability: false)}` not have a supported fromJson definition.', - // ignore: experimental_member_use - element: type.element3, + '`${withoutNullability(type.getDisplayString())}` not have a supported fromJson definition.', + element: type.element, ); } @@ -759,9 +755,9 @@ class _TypeHelperJson extends _TypeHelperWithHelper { bool _isNestedTemplate(InterfaceType type) { // check if has fromJson constructor - // ignore: experimental_member_use - final ConstructorElement2? fromJsonMethod = type.element3 - .getNamedConstructor2('fromJson'); + final ConstructorElement? fromJsonMethod = type.element.getNamedConstructor( + 'fromJson', + ); if (fromJsonMethod == null || !fromJsonMethod.isPublic) { return false; } @@ -778,13 +774,12 @@ class _TypeHelperJson extends _TypeHelperWithHelper { } final FormalParameterElement firstParam = parameters[0]; - if (firstParam.type.getDisplayString(withNullability: false) != + if (withoutNullability(firstParam.type.getDisplayString()) != 'Map') { throw InvalidGenerationSourceError( 'The parameter type ' - '`${type.getDisplayString(withNullability: false)}` not have a supported fromJson definition.', - // ignore: experimental_member_use - element: type.element3, + '`${withoutNullability(type.getDisplayString())}` not have a supported fromJson definition.', + element: type.element, ); } @@ -795,17 +790,14 @@ class _TypeHelperJson extends _TypeHelperWithHelper { } final functionType = secondParam.type as FunctionType; - // ignore: experimental_member_use if (functionType.formalParameters.length != 1 || functionType.returnType.getDisplayString() != type.element.typeParameters.first.displayName || - // ignore: experimental_member_use functionType.formalParameters[0].type.getDisplayString() != 'Object?') { throw InvalidGenerationSourceError( 'The parameter type ' - '`${type.getDisplayString(withNullability: false)}` not have a supported fromJson definition.', - // ignore: experimental_member_use - element: type.element3, + '`${withoutNullability(type.getDisplayString())}` not have a supported fromJson definition.', + element: type.element, ); } @@ -866,7 +858,7 @@ extension FormalParameterElementExtension on FormalParameterElement { /// An error thrown when a default value is used with a nullable type. class NullableDefaultValueError extends InvalidGenerationSourceError { /// An error thrown when a default value is used with a nullable type. - NullableDefaultValueError(Element2 element) + NullableDefaultValueError(Element element) : super( 'Default value used with a nullable type. Only non-nullable type can have a default value.', todo: 'Remove the default value or make the type non-nullable.', diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 684ad1ed8a4..1f2000c255d 100644 --- a/packages/go_router_builder/pubspec.yaml +++ b/packages/go_router_builder/pubspec.yaml @@ -2,7 +2,7 @@ name: go_router_builder description: >- A builder that supports generated strongly-typed route helpers for package:go_router -version: 4.1.1 +version: 4.1.2 repository: https://github.com/flutter/packages/tree/main/packages/go_router_builder issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router_builder%22 @@ -11,7 +11,7 @@ environment: flutter: ">=3.32.0" dependencies: - analyzer: ">=7.4.0 <9.0.0" + analyzer: ">=8.1.0 <10.0.0" async: ^2.8.0 # TODO(piinks): Pin version once new stable rolls. build: ">=3.0.0 <5.0.0" diff --git a/packages/go_router_builder/tool/run_tests.dart b/packages/go_router_builder/tool/run_tests.dart index 4ddb1de7db2..d1b8b84acc6 100644 --- a/packages/go_router_builder/tool/run_tests.dart +++ b/packages/go_router_builder/tool/run_tests.dart @@ -5,7 +5,7 @@ import 'dart:io'; import 'dart:isolate'; -import 'package:analyzer/dart/element/element2.dart'; +import 'package:analyzer/dart/element/element.dart'; import 'package:build/build.dart'; import 'package:build_test/build_test.dart'; import 'package:dart_style/dart_style.dart' as dart_style; @@ -42,7 +42,7 @@ Future main() async { // Normalize path separators for cross-platform compatibility final String path = file.path.replaceAll(r'\', '/'); final targetLibraryAssetId = '__test__|$path'; - final LibraryElement2 element = await resolveSources( + final LibraryElement element = await resolveSources( {targetLibraryAssetId: file.readAsStringSync()}, (Resolver resolver) async { final assetId = AssetId.parse(targetLibraryAssetId);