mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-03-25 04:40:33 +00:00
feat: migrate to analyzer 9.0.0 API
- Replace Element2 API with Element API - Update imports from element2.dart to element.dart - Replace .firstFragment.name2 with .name - Replace .firstFragment.metadata2.annotations with .metadata.annotations - Replace .fields2 with .fields - Replace .methods2 with .methods - Remove duplicate imports in annotation_validator.dart and generated_class.dart - Update test mocks to use Element instead of Element2 All generators now work correctly with analyzer 9.0.0: - melos analyze: SUCCESS (0 issues) - melos codegen: SUCCESS (13 outputs generated) - melos bootstrap: SUCCESS (8 packages)
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
//
|
||||
|
||||
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:build/build.dart';
|
||||
@@ -100,11 +100,11 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||
/// ```
|
||||
@override
|
||||
dynamic generateForAnnotatedElement(
|
||||
Element2 element,
|
||||
Element element,
|
||||
ConstantReader annotation,
|
||||
BuildStep buildStep,
|
||||
) {
|
||||
if (element is! ClassElement2) {
|
||||
if (element is! ClassElement) {
|
||||
throw InvalidGenerationSourceError(
|
||||
'@injectable() can only be applied to classes.',
|
||||
element: element,
|
||||
@@ -112,7 +112,7 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||
}
|
||||
|
||||
final classElement = element;
|
||||
final className = classElement.firstFragment.name2;
|
||||
final className = classElement.name;
|
||||
final mixinName = '_\$$className';
|
||||
|
||||
final buffer = StringBuffer()
|
||||
@@ -120,7 +120,7 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||
..writeln(' void _inject($className instance) {');
|
||||
|
||||
// Collect and process all @inject fields
|
||||
final injectFields = classElement.fields2
|
||||
final injectFields = classElement.fields
|
||||
.where((f) => _isInjectField(f))
|
||||
.map((f) => _parseInjectField(f));
|
||||
|
||||
@@ -138,8 +138,8 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||
/// Returns true if a field is annotated with `@inject`.
|
||||
///
|
||||
/// Used to detect which fields should be processed for injection.
|
||||
static bool _isInjectField(FieldElement2 field) {
|
||||
return field.firstFragment.metadata2.annotations.any(
|
||||
static bool _isInjectField(FieldElement field) {
|
||||
return field.metadata.annotations.any(
|
||||
(m) => m.computeConstantValue()?.type?.getDisplayString() == 'inject',
|
||||
);
|
||||
}
|
||||
@@ -149,11 +149,11 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||
///
|
||||
/// Converts Dart field declaration and all parameterizing injection-related
|
||||
/// annotations into a [_ParsedInjectField] which is used for codegen.
|
||||
static _ParsedInjectField _parseInjectField(FieldElement2 field) {
|
||||
static _ParsedInjectField _parseInjectField(FieldElement field) {
|
||||
String? scopeName;
|
||||
String? namedValue;
|
||||
|
||||
for (final meta in field.firstFragment.metadata2.annotations) {
|
||||
for (final meta in field.metadata.annotations) {
|
||||
final DartObject? obj = meta.computeConstantValue();
|
||||
final type = obj?.type?.getDisplayString();
|
||||
if (type == 'scope') {
|
||||
@@ -185,7 +185,7 @@ class InjectGenerator extends GeneratorForAnnotation<ann.injectable> {
|
||||
));
|
||||
|
||||
return _ParsedInjectField(
|
||||
fieldName: field.firstFragment.name2 ?? '',
|
||||
fieldName: field.name!,
|
||||
coreType: coreTypeName.replaceAll('?', ''), // удаляем "?" на всякий
|
||||
isFuture: isFuture,
|
||||
isNullable: isNullable,
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import 'package:analyzer/dart/element/element2.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:build/build.dart';
|
||||
import 'package:source_gen/source_gen.dart';
|
||||
import 'package:cherrypick_annotations/cherrypick_annotations.dart' as ann;
|
||||
@@ -80,11 +80,11 @@ class ModuleGenerator extends GeneratorForAnnotation<ann.module> {
|
||||
/// See file-level docs for usage and generated output example.
|
||||
@override
|
||||
dynamic generateForAnnotatedElement(
|
||||
Element2 element,
|
||||
Element element,
|
||||
ConstantReader annotation,
|
||||
BuildStep buildStep,
|
||||
) {
|
||||
if (element is! ClassElement2) {
|
||||
if (element is! ClassElement) {
|
||||
throw InvalidGenerationSourceError(
|
||||
'@module() can only be applied to classes.',
|
||||
element: element,
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
//
|
||||
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/element2.dart';
|
||||
import 'exceptions.dart';
|
||||
import 'metadata_utils.dart';
|
||||
|
||||
@@ -53,9 +52,9 @@ class AnnotationValidator {
|
||||
/// - Parameter validation for method arguments.
|
||||
///
|
||||
/// Throws [AnnotationValidationException] on any violation.
|
||||
static void validateMethodAnnotations(MethodElement2 method) {
|
||||
static void validateMethodAnnotations(MethodElement method) {
|
||||
final annotations = _getAnnotationNames(
|
||||
method.firstFragment.metadata2.annotations,
|
||||
method.metadata.annotations,
|
||||
);
|
||||
|
||||
_validateMutuallyExclusiveAnnotations(method, annotations);
|
||||
@@ -71,9 +70,9 @@ class AnnotationValidator {
|
||||
/// - Correct scope naming if present.
|
||||
///
|
||||
/// Throws [AnnotationValidationException] if checks fail.
|
||||
static void validateFieldAnnotations(FieldElement2 field) {
|
||||
static void validateFieldAnnotations(FieldElement field) {
|
||||
final annotations = _getAnnotationNames(
|
||||
field.firstFragment.metadata2.annotations,
|
||||
field.metadata.annotations,
|
||||
);
|
||||
|
||||
_validateInjectFieldAnnotations(field, annotations);
|
||||
@@ -87,9 +86,9 @@ class AnnotationValidator {
|
||||
/// - Provides helpful context for error/warning reporting.
|
||||
///
|
||||
/// Throws [AnnotationValidationException] if checks fail.
|
||||
static void validateClassAnnotations(ClassElement2 classElement) {
|
||||
static void validateClassAnnotations(ClassElement classElement) {
|
||||
final annotations = _getAnnotationNames(
|
||||
classElement.firstFragment.metadata2.annotations,
|
||||
classElement.metadata.annotations,
|
||||
);
|
||||
|
||||
_validateModuleClassAnnotations(classElement, annotations);
|
||||
@@ -111,7 +110,7 @@ class AnnotationValidator {
|
||||
///
|
||||
/// For example, `@instance` and `@provide` cannot both be present.
|
||||
static void _validateMutuallyExclusiveAnnotations(
|
||||
MethodElement2 method,
|
||||
MethodElement method,
|
||||
List<String> annotations,
|
||||
) {
|
||||
// @instance and @provide are mutually exclusive
|
||||
@@ -134,7 +133,7 @@ class AnnotationValidator {
|
||||
/// - One of `@instance` or `@provide` must be present for a registration method
|
||||
/// - Validates singleton usage
|
||||
static void _validateAnnotationCombinations(
|
||||
MethodElement2 method,
|
||||
MethodElement method,
|
||||
List<String> annotations,
|
||||
) {
|
||||
// @params can only be used with @provide
|
||||
@@ -172,7 +171,7 @@ class AnnotationValidator {
|
||||
|
||||
/// Singleton-specific method annotation checks.
|
||||
static void _validateSingletonUsage(
|
||||
MethodElement2 method,
|
||||
MethodElement method,
|
||||
List<String> annotations,
|
||||
) {
|
||||
// Singleton with params might not make sense in some contexts
|
||||
@@ -194,10 +193,10 @@ class AnnotationValidator {
|
||||
}
|
||||
|
||||
/// Validates extra requirements or syntactic rules for annotation arguments, like @named.
|
||||
static void _validateAnnotationParameters(MethodElement2 method) {
|
||||
static void _validateAnnotationParameters(MethodElement method) {
|
||||
// Validate @named annotation parameters
|
||||
final namedValue = MetadataUtils.getNamedValue(
|
||||
method.firstFragment.metadata2.annotations,
|
||||
method.metadata.annotations,
|
||||
);
|
||||
if (namedValue != null) {
|
||||
if (namedValue.isEmpty) {
|
||||
@@ -230,7 +229,7 @@ class AnnotationValidator {
|
||||
// Validate method parameters for @params usage
|
||||
for (final param in method.formalParameters) {
|
||||
final paramAnnotations = _getAnnotationNames(
|
||||
param.firstFragment.metadata2.annotations,
|
||||
param.metadata.annotations,
|
||||
);
|
||||
if (paramAnnotations.contains('params')) {
|
||||
_validateParamsParameter(param, method);
|
||||
@@ -241,7 +240,7 @@ class AnnotationValidator {
|
||||
/// Checks that @params is used with compatible parameter type.
|
||||
static void _validateParamsParameter(
|
||||
FormalParameterElement param,
|
||||
MethodElement2 method,
|
||||
MethodElement method,
|
||||
) {
|
||||
// @params parameter should typically be dynamic or Map<String, dynamic>
|
||||
final paramType = param.type.getDisplayString();
|
||||
@@ -266,7 +265,7 @@ class AnnotationValidator {
|
||||
|
||||
/// Checks field-level annotation for valid injectable fields.
|
||||
static void _validateInjectFieldAnnotations(
|
||||
FieldElement2 field,
|
||||
FieldElement field,
|
||||
List<String> annotations,
|
||||
) {
|
||||
if (!annotations.contains('inject')) {
|
||||
@@ -285,7 +284,7 @@ class AnnotationValidator {
|
||||
}
|
||||
|
||||
// Validate scope annotation if present
|
||||
for (final meta in field.firstFragment.metadata2.annotations) {
|
||||
for (final meta in field.metadata.annotations) {
|
||||
final obj = meta.computeConstantValue();
|
||||
final type = obj?.type?.getDisplayString();
|
||||
if (type == 'scope') {
|
||||
@@ -297,7 +296,7 @@ class AnnotationValidator {
|
||||
|
||||
/// Checks @module usage: must have at least one DI method, each with DI-annotation.
|
||||
static void _validateModuleClassAnnotations(
|
||||
ClassElement2 classElement,
|
||||
ClassElement classElement,
|
||||
List<String> annotations,
|
||||
) {
|
||||
if (!annotations.contains('module')) {
|
||||
@@ -305,7 +304,7 @@ class AnnotationValidator {
|
||||
}
|
||||
|
||||
// Check if class has public methods
|
||||
final publicMethods = classElement.methods2
|
||||
final publicMethods = classElement.methods
|
||||
.where((m) => m.isPublic)
|
||||
.toList();
|
||||
if (publicMethods.isEmpty) {
|
||||
@@ -323,7 +322,7 @@ class AnnotationValidator {
|
||||
// Validate that public methods have appropriate annotations
|
||||
for (final method in publicMethods) {
|
||||
final methodAnnotations = _getAnnotationNames(
|
||||
method.firstFragment.metadata2.annotations,
|
||||
method.metadata.annotations,
|
||||
);
|
||||
if (!methodAnnotations.contains('instance') &&
|
||||
!methodAnnotations.contains('provide')) {
|
||||
@@ -342,7 +341,7 @@ class AnnotationValidator {
|
||||
|
||||
/// Checks @injectable usage on classes and their fields.
|
||||
static void _validateInjectableClassAnnotations(
|
||||
ClassElement2 classElement,
|
||||
ClassElement classElement,
|
||||
List<String> annotations,
|
||||
) {
|
||||
if (!annotations.contains('injectable')) {
|
||||
@@ -350,9 +349,9 @@ class AnnotationValidator {
|
||||
}
|
||||
|
||||
// Check if class has injectable fields
|
||||
final injectFields = classElement.fields2.where((f) {
|
||||
final injectFields = classElement.fields.where((f) {
|
||||
final fieldAnnotations = _getAnnotationNames(
|
||||
f.firstFragment.metadata2.annotations,
|
||||
f.metadata.annotations,
|
||||
);
|
||||
return fieldAnnotations.contains('inject');
|
||||
}).toList();
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import 'package:analyzer/dart/element/element2.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
|
||||
import 'bind_parameters_spec.dart';
|
||||
import 'metadata_utils.dart';
|
||||
@@ -251,7 +251,7 @@ class BindSpec {
|
||||
/// print(bindSpec.returnType); // e.g., 'Logger'
|
||||
/// ```
|
||||
/// Throws [AnnotationValidationException] or [CodeGenerationException] if invalid.
|
||||
static BindSpec fromMethod(MethodElement2 method) {
|
||||
static BindSpec fromMethod(MethodElement method) {
|
||||
try {
|
||||
// Validate method annotations
|
||||
AnnotationValidator.validateMethodAnnotations(method);
|
||||
@@ -259,17 +259,17 @@ class BindSpec {
|
||||
// Parse return type using improved type parser
|
||||
final parsedReturnType = TypeParser.parseType(method.returnType, method);
|
||||
|
||||
final methodName = method.firstFragment.name2 ?? '';
|
||||
final methodName = method.name ?? '';
|
||||
|
||||
// Check for @singleton annotation.
|
||||
final isSingleton = MetadataUtils.anyMeta(
|
||||
method.firstFragment.metadata2.annotations,
|
||||
method.metadata.annotations,
|
||||
'singleton',
|
||||
);
|
||||
|
||||
// Get @named value if present.
|
||||
final named = MetadataUtils.getNamedValue(
|
||||
method.firstFragment.metadata2.annotations,
|
||||
method.metadata.annotations,
|
||||
);
|
||||
|
||||
// Parse each method parameter.
|
||||
@@ -278,10 +278,10 @@ class BindSpec {
|
||||
for (final p in method.formalParameters) {
|
||||
final typeStr = p.type.getDisplayString();
|
||||
final paramNamed = MetadataUtils.getNamedValue(
|
||||
p.firstFragment.metadata2.annotations,
|
||||
p.metadata.annotations,
|
||||
);
|
||||
final isParams = MetadataUtils.anyMeta(
|
||||
p.firstFragment.metadata2.annotations,
|
||||
p.metadata.annotations,
|
||||
'params',
|
||||
);
|
||||
if (isParams) hasParams = true;
|
||||
@@ -290,11 +290,11 @@ class BindSpec {
|
||||
|
||||
// Determine bindingType: @instance or @provide.
|
||||
final hasInstance = MetadataUtils.anyMeta(
|
||||
method.firstFragment.metadata2.annotations,
|
||||
method.metadata.annotations,
|
||||
'instance',
|
||||
);
|
||||
final hasProvide = MetadataUtils.anyMeta(
|
||||
method.firstFragment.metadata2.annotations,
|
||||
method.metadata.annotations,
|
||||
'provide',
|
||||
);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import 'package:analyzer/dart/element/element2.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:source_gen/source_gen.dart';
|
||||
|
||||
/// ---------------------------------------------------------------------------
|
||||
@@ -48,7 +48,7 @@ class CherryPickGeneratorException extends InvalidGenerationSourceError {
|
||||
|
||||
CherryPickGeneratorException(
|
||||
String message, {
|
||||
required Element2 element,
|
||||
required Element element,
|
||||
required this.category,
|
||||
this.suggestion,
|
||||
this.context,
|
||||
@@ -62,7 +62,7 @@ class CherryPickGeneratorException extends InvalidGenerationSourceError {
|
||||
String category,
|
||||
String? suggestion,
|
||||
Map<String, dynamic>? context,
|
||||
Element2 element,
|
||||
Element element,
|
||||
) {
|
||||
final buffer = StringBuffer();
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
//
|
||||
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/element2.dart';
|
||||
import 'bind_spec.dart';
|
||||
|
||||
/// ---------------------------------------------------------------------------
|
||||
@@ -76,11 +75,11 @@ class GeneratedClass {
|
||||
/// final gen = GeneratedClass.fromClassElement(classElement);
|
||||
/// print(gen.generatedClassName); // e.g. $AppModule
|
||||
/// ```
|
||||
static GeneratedClass fromClassElement(ClassElement2 element) {
|
||||
final className = element.firstFragment.name2 ?? '';
|
||||
static GeneratedClass fromClassElement(ClassElement element) {
|
||||
final className = element.name ?? '';
|
||||
final generatedClassName = r'$' + className;
|
||||
final sourceFile = element.firstFragment.libraryFragment.source.shortName;
|
||||
final binds = element.methods2
|
||||
final binds = element.methods
|
||||
.where((m) => !m.isAbstract)
|
||||
.map(BindSpec.fromMethod)
|
||||
.toList();
|
||||
|
||||
@@ -23,10 +23,10 @@ import 'package:analyzer/dart/element/element.dart';
|
||||
///
|
||||
/// # Example usage
|
||||
/// ```dart
|
||||
/// if (MetadataUtils.anyMeta(method.metadata, 'singleton')) {
|
||||
/// if (MetadataUtils.anyMeta(method.metadata.annotations, 'singleton')) {
|
||||
/// // The method is annotated with @singleton
|
||||
/// }
|
||||
/// final name = MetadataUtils.getNamedValue(field.metadata);
|
||||
/// final name = MetadataUtils.getNamedValue(field.metadata.annotations);
|
||||
/// if (name != null) print('@named value: $name');
|
||||
/// ```
|
||||
/// ---------------------------------------------------------------------------
|
||||
@@ -38,7 +38,7 @@ class MetadataUtils {
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// bool isSingleton = MetadataUtils.anyMeta(myMethod.metadata, 'singleton');
|
||||
/// bool isSingleton = MetadataUtils.anyMeta(myMethod.metadata.annotations, 'singleton');
|
||||
/// ```
|
||||
static bool anyMeta(List<ElementAnnotation> meta, String typeName) {
|
||||
return meta.any(
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
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 'exceptions.dart';
|
||||
@@ -45,7 +45,7 @@ class TypeParser {
|
||||
/// final parsed = TypeParser.parseType(field.type, field);
|
||||
/// if (parsed.isNullable) print('Field is nullable');
|
||||
/// ```
|
||||
static ParsedType parseType(DartType dartType, Element2 context) {
|
||||
static ParsedType parseType(DartType dartType, Element context) {
|
||||
try {
|
||||
return _parseTypeInternal(dartType, context);
|
||||
} catch (e) {
|
||||
@@ -61,7 +61,7 @@ class TypeParser {
|
||||
}
|
||||
}
|
||||
|
||||
static ParsedType _parseTypeInternal(DartType dartType, Element2 context) {
|
||||
static ParsedType _parseTypeInternal(DartType dartType, Element context) {
|
||||
final displayString = dartType.getDisplayString();
|
||||
final isNullable = dartType.nullabilitySuffix == NullabilitySuffix.question;
|
||||
|
||||
@@ -88,7 +88,7 @@ class TypeParser {
|
||||
|
||||
static ParsedType _parseFutureType(
|
||||
DartType dartType,
|
||||
Element2 context,
|
||||
Element context,
|
||||
bool isNullable,
|
||||
) {
|
||||
if (dartType is! ParameterizedType || dartType.typeArguments.isEmpty) {
|
||||
@@ -116,7 +116,7 @@ class TypeParser {
|
||||
|
||||
static ParsedType _parseGenericType(
|
||||
ParameterizedType dartType,
|
||||
Element2 context,
|
||||
Element context,
|
||||
bool isNullable,
|
||||
) {
|
||||
final typeArguments = dartType.typeArguments
|
||||
@@ -144,7 +144,7 @@ class TypeParser {
|
||||
/// final parsed = TypeParser.parseType(field.type, field);
|
||||
/// TypeParser.validateInjectableType(parsed, field);
|
||||
/// ```
|
||||
static void validateInjectableType(ParsedType parsedType, Element2 context) {
|
||||
static void validateInjectableType(ParsedType parsedType, Element context) {
|
||||
// Check for void type
|
||||
if (parsedType.coreType == 'void') {
|
||||
throw TypeParsingException(
|
||||
|
||||
Reference in New Issue
Block a user