Skip to content

Commit

Permalink
- Chore: Update dependencies, source_gen (v2), analyzer (<8.0.0), dar…
Browse files Browse the repository at this point in the history
…t_style (v3)
  • Loading branch information
Milad-Akarie committed Jan 14, 2025
1 parent 41602aa commit 9aa237b
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 188 deletions.
4 changes: 2 additions & 2 deletions injectable/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ dependencies:

dev_dependencies:
pedantic: ^1.11.1
build_runner: ^2.4.0
build_runner: ^2.4.14
effective_dart: ^1.3.2
lints: ^2.1.0
lints: ^5.1.1
injectable_generator:
path: ../../injectable_generator
2 changes: 1 addition & 1 deletion injectable/lib/src/injectable_annotations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class InjectableInit {
/// feature flag to activate a 'constructor callback'.
/// Setting this to 'true' will generate an additional parameter
/// to '$initGetIt' - named "constructorCallback" - a function of signature
/// "T constructorCallback<T>(T)".
/// "T constructorCallback%lt;T%gt;(T)".
/// Injectable will pass all injectable objects to this delegate at the
/// time of their constructor/module-method invocation.
/// defaults to false
Expand Down
6 changes: 3 additions & 3 deletions injectable/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ packages:
dependency: "direct dev"
description:
name: lints
sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
url: "https://pub.dev"
source: hosted
version: "5.0.0"
version: "5.1.1"
meta:
dependency: "direct main"
description:
Expand All @@ -42,4 +42,4 @@ packages:
source: hosted
version: "1.15.0"
sdks:
dart: ">=3.5.0 <4.0.0"
dart: ">=3.6.0 <4.0.0"
3 changes: 2 additions & 1 deletion injectable_generator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# ChangeLog

## [2.7.0]
- Chore: Update dependencies, source_gen (v2), analyzer (<8.0.0), dart_style (v3)
## [2.6.2]
- Feat: Improve Code Generation consistency using hash in alias imports
- Fix: Fix @preResolve only works for methods warning
Expand Down
7 changes: 5 additions & 2 deletions injectable_generator/lib/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import 'generators/injectable_generator.dart';
Builder injectableBuilder(BuilderOptions options) {
return LibraryBuilder(
InjectableGenerator(options.config),
formatOutput: (generated, _) => generated.replaceAll(RegExp(r'//.*|\s'), ''),
formatOutput: (generated, _) =>
generated.replaceAll(RegExp(r'//.*|\s'), ''),
generatedExtension: '.injectable.json',
);
}

Builder injectableConfigBuilder(BuilderOptions options) {
return LibraryBuilder(InjectableConfigGenerator(), generatedExtension: '.config.dart', additionalOutputExtensions: ['.module.dart']);
return LibraryBuilder(InjectableConfigGenerator(),
generatedExtension: '.config.dart',
additionalOutputExtensions: ['.module.dart']);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,31 @@ import 'package:injectable_generator/utils.dart';

class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
@override
dynamic generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) async {
final generateForDir = annotation.read('generateForDir').listValue.map((e) => e.toStringValue());
dynamic generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) async {
final generateForDir = annotation
.read('generateForDir')
.listValue
.map((e) => e.toStringValue());

final usesNullSafety = annotation.read('usesNullSafety').boolValue;
final isMicroPackage = annotation.read('_isMicroPackage').boolValue;
final usesConstructorCallback = annotation.read('usesConstructorCallback').boolValue;
final throwOnMissingDependencies = annotation.read('throwOnMissingDependencies').boolValue;
final usesConstructorCallback =
annotation.read('usesConstructorCallback').boolValue;
final throwOnMissingDependencies =
annotation.read('throwOnMissingDependencies').boolValue;
final targetFile = element.source?.uri;
final preferRelativeImports = annotation.read("preferRelativeImports").boolValue;
final preferRelativeImports =
annotation.read("preferRelativeImports").boolValue;

final includeMicroPackages = annotation.read("includeMicroPackages").boolValue;
final includeMicroPackages =
annotation.read("includeMicroPackages").boolValue;

final rootDir = annotation.peek('rootDir')?.stringValue;

final dirPattern = generateForDir.length > 1 ? '{${generateForDir.join(',')}}' : '${generateForDir.first}';
final dirPattern = generateForDir.length > 1
? '{${generateForDir.join(',')}}'
: '${generateForDir.first}';

final injectableConfigFiles = Glob("$dirPattern/**.injectable.json");

Expand All @@ -54,11 +64,13 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
final initializerName = annotation.read('initializerName').stringValue;
final asExtension = annotation.read('asExtension').boolValue;

final typeResolver = ImportableTypeResolverImpl(await buildStep.resolver.libraries.toList());
final typeResolver =
ImportableTypeResolverImpl(await buildStep.resolver.libraries.toList());

final ignoredTypes = annotation.read('ignoreUnregisteredTypes').listValue.map(
(e) => typeResolver.resolveType(e.toTypeValue()!),
);
final ignoredTypes =
annotation.read('ignoreUnregisteredTypes').listValue.map(
(e) => typeResolver.resolveType(e.toTypeValue()!),
);

final microPackageModulesBefore = _getMicroPackageModules(
annotation.peek('externalPackageModulesBefore'),
Expand All @@ -80,7 +92,8 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
typeResolver,
);

final microPackagesModules = microPackageModulesBefore.union(microPackageModulesAfter);
final microPackagesModules =
microPackageModulesBefore.union(microPackageModulesAfter);
if (!isMicroPackage && includeMicroPackages) {
final glob = Glob('**.module.dart', recursive: true);
final filesStream = glob.list(root: rootDir);
Expand All @@ -96,7 +109,8 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
import: segments[2],
),
);
if (!microPackagesModules.any((e) => externalModule.module == e.module)) {
if (!microPackagesModules
.any((e) => externalModule.module == e.module)) {
microPackageModulesBefore.add(externalModule);
}
}
Expand All @@ -115,7 +129,8 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
// we want to ignore unregistered types in microPackages
// because the micro module should handle them
for (final pckModule in microPackagesModules) {
final packageName = Uri.parse(pckModule.module.import!).pathSegments.first;
final packageName =
Uri.parse(pckModule.module.import!).pathSegments.first;
ignoreTypesInPackages.add(packageName);
}

Expand Down Expand Up @@ -144,7 +159,8 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
targetFile: preferRelativeImports ? targetFile : null,
initializerName: initializerName,
asExtension: asExtension,
microPackageName: isMicroPackage ? buildStep.inputId.package.pascalCase : null,
microPackageName:
isMicroPackage ? buildStep.inputId.package.pascalCase : null,
microPackagesModulesBefore: microPackageModulesBefore,
microPackagesModulesAfter: microPackageModulesAfter,
usesConstructorCallback: usesConstructorCallback,
Expand Down Expand Up @@ -185,10 +201,13 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
final typeValue = reader.read('module').typeValue;
final scope = reader.peek('scope')?.stringValue;
throwIf(
typeValue.element is! ClassElement || !TypeChecker.fromRuntime(MicroPackageModule).isSuperOf(typeValue.element!),
typeValue.element is! ClassElement ||
!TypeChecker.fromRuntime(MicroPackageModule)
.isSuperOf(typeValue.element!),
'ExternalPackageModule must be a class that extends MicroPackageModule',
);
return ExternalModuleConfig(typeResolver.resolveType(typeValue), scope);
return ExternalModuleConfig(
typeResolver.resolveType(typeValue), scope);
},
).toSet() ??
<ExternalModuleConfig>{};
Expand All @@ -202,7 +221,9 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
(e) {
final typeValue = e.toTypeValue()!;
throwIf(
typeValue.element is! ClassElement || !TypeChecker.fromRuntime(MicroPackageModule).isSuperOf(typeValue.element!),
typeValue.element is! ClassElement ||
!TypeChecker.fromRuntime(MicroPackageModule)
.isSuperOf(typeValue.element!),
'ExternalPackageModule must be a class that extends MicroPackageModule',
);
return ExternalModuleConfig(typeResolver.resolveType(typeValue));
Expand All @@ -220,7 +241,8 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
) {
final messages = [];
for (final dep in deps) {
for (var iDep in dep.dependencies.where((d) => !d.isFactoryParam && d.instanceName != kEnvironmentsName)) {
for (var iDep in dep.dependencies.where(
(d) => !d.isFactoryParam && d.instanceName != kEnvironmentsName)) {
if ((ignoredTypes.contains(iDep.type) ||
(iDep.type.import == null ||
ignoredTypesInPackages.any(
Expand All @@ -235,9 +257,13 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
messages.add(
"[${dep.typeImpl}] depends on unregistered type [${iDep.type}] ${iDep.type.import == null ? '' : 'from ${iDep.type.import}'}");
} else {
final availableEnvs = possibleDeps.map((e) => e.environments).reduce((a, b) => a + b).toSet();
final availableEnvs = possibleDeps
.map((e) => e.environments)
.reduce((a, b) => a + b)
.toSet();
if (availableEnvs.isNotEmpty) {
final missingEnvs = dep.environments.toSet().difference(availableEnvs);
final missingEnvs =
dep.environments.toSet().difference(availableEnvs);
if (missingEnvs.isNotEmpty) {
messages.add(
'[${dep.typeImpl}] ${dep.environments.toSet()} depends on Type [${iDep.type}] ${iDep.type.import == null ? '' : 'from ${iDep.type.import}'} \n which is not available under environment keys $missingEnvs',
Expand All @@ -252,23 +278,30 @@ class InjectableConfigGenerator extends GeneratorForAnnotation<InjectableInit> {
messages.add(
'\nDid you forget to annotate the above class(s) or their implementation with @injectable? \nor add the right environment keys?');
throwIf(throwOnMissingDependencies, messages.join('\n'));
printBoxed(messages.join('\n'), header: "Missing dependencies in ${targetFile?.path}\n");
printBoxed(messages.join('\n'),
header: "Missing dependencies in ${targetFile?.path}\n");
}
}

void _validateDuplicateDependencies(List<DependencyConfig> deps) {
final validatedDeps = <DependencyConfig>[];
for (var dep in deps) {
var registered = validatedDeps.where(
(elm) => elm.type == dep.type && elm.instanceName == dep.instanceName && elm.scope == dep.scope,
(elm) =>
elm.type == dep.type &&
elm.instanceName == dep.instanceName &&
elm.scope == dep.scope,
);

if (registered.isEmpty) {
validatedDeps.add(dep);
} else {
Set<String> registeredEnvironments = registered.fold(<String>{}, (prev, elm) => prev..addAll(elm.environments));
Set<String> registeredEnvironments = registered
.fold(<String>{}, (prev, elm) => prev..addAll(elm.environments));

if (registeredEnvironments.isEmpty || dep.environments.any((env) => registeredEnvironments.contains(env))) {
if (registeredEnvironments.isEmpty ||
dep.environments
.any((env) => registeredEnvironments.contains(env))) {
throwBoxed(
'${dep.typeImpl} [${dep.type}] envs: ${dep.environments} scope: ${dep.scope} \nis registered more than once under the same environment or in the same scope',
);
Expand Down
16 changes: 7 additions & 9 deletions injectable_generator/lib/resolvers/dependency_resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class DependencyResolver {
final returnType = executableElement.returnType;
throwIf(
returnType.element is! ClassElement,
'${returnType.getDisplayString(withNullability: false)} is not a class element',
'${returnType.nameWithoutSuffix} is not a class element',
element: returnType.element,
);

Expand Down Expand Up @@ -148,11 +148,11 @@ class DependencyResolver {
if (abstractType != null) {
final abstractChecker = TypeChecker.fromStatic(abstractType);
var abstractSubtype = clazz.allSupertypes
.firstOrNull((type) => abstractChecker.isExactly(type.element));
.firstWhereOrNull((type) => abstractChecker.isExactly(type.element));

throwIf(
abstractSubtype == null,
'[${clazz.name}] is not a subtype of [${abstractType.getDisplayString(withNullability: false)}]',
'[${clazz.name}] is not a subtype of [${abstractType.nameWithoutSuffix}]',
element: clazz,
);

Expand Down Expand Up @@ -190,7 +190,7 @@ class DependencyResolver {
}

var disposeMethod = clazz.methods
.firstOrNull((m) => _disposeMethodChecker.hasAnnotationOfExact(m));
.firstWhereOrNull((m) => _disposeMethodChecker.hasAnnotationOfExact(m));
if (disposeMethod != null) {
throwIf(
_injectableType == InjectableType.factory,
Expand Down Expand Up @@ -266,11 +266,9 @@ class DependencyResolver {
continue;
}
final namedAnnotation = _namedChecker.firstAnnotationOf(param);
final instanceName = namedAnnotation
?.getField('type')
?.toTypeValue()
?.getDisplayString(withNullability: false) ??
namedAnnotation?.getField('name')?.toStringValue();
final instanceName =
namedAnnotation?.getField('type')?.toTypeValue()?.nameWithoutSuffix ??
namedAnnotation?.getField('name')?.toStringValue();

final resolvedType = param.type is FunctionType
? _typeResolver.resolveFunctionType(param.type as FunctionType)
Expand Down
11 changes: 5 additions & 6 deletions injectable_generator/lib/resolvers/importable_type_resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:collection/collection.dart';
import 'package:injectable_generator/models/importable_type.dart';
import 'package:injectable_generator/utils.dart';
import 'package:path/path.dart' as p;

abstract class ImportableTypeResolver {
Expand Down Expand Up @@ -79,13 +80,13 @@ class ImportableTypeResolverImpl extends ImportableTypeResolver {
final functionElement =
executableElement ?? function.element ?? function.alias?.element;
if (functionElement == null) {
throw 'Can not resolve function type \nTry using an alias e.g typedef MyFunction = ${function.getDisplayString(withNullability: false)};';
throw 'Can not resolve function type \nTry using an alias e.g typedef MyFunction = ${function.nameWithoutSuffix};';
}
final displayName = functionElement.displayName;
var functionName = displayName;

Element elementToImport = functionElement;
var enclosingElement = functionElement.enclosingElement;
var enclosingElement = functionElement.enclosingElement3;

if (enclosingElement != null && enclosingElement is ClassElement) {
functionName = '${enclosingElement.displayName}.$displayName';
Expand Down Expand Up @@ -140,8 +141,7 @@ class ImportableTypeResolverImpl extends ImportableTypeResolver {
importableTypes.add(ImportableType(name: 'dynamic'));
} else {
importableTypes.add(ImportableType(
name: type.element?.name ??
type.getDisplayString(withNullability: false),
name: type.element?.name ?? type.nameWithoutSuffix,
import: imports.firstOrNull,
otherImports: imports.skip(1).toSet(),
isNullable: type.nullabilitySuffix == NullabilitySuffix.question,
Expand All @@ -167,8 +167,7 @@ class ImportableTypeResolverImpl extends ImportableTypeResolver {
);
}
return ImportableType(
name: effectiveElement?.displayName ??
type.getDisplayString(withNullability: false),
name: effectiveElement?.displayName ?? type.nameWithoutSuffix,
isNullable: type.nullabilitySuffix == NullabilitySuffix.question,
import: imports.firstOrNull,
otherImports: imports.skip(1).toSet(),
Expand Down
13 changes: 12 additions & 1 deletion injectable_generator/lib/utils.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// general utils
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:source_gen/source_gen.dart';

String capitalize(String s) {
Expand Down Expand Up @@ -49,7 +50,7 @@ void printBoxed(String message,
}

extension IterableExtenstion<E> on Iterable<E> {
E? firstOrNull(bool Function(E element) test) {
E? firstWhereOrNull(bool Function(E element) test) {
for (var e in this) {
if (test(e)) {
return e;
Expand All @@ -58,3 +59,13 @@ extension IterableExtenstion<E> on Iterable<E> {
return null;
}
}

/// Extension helpers for [DartType]
extension DartTypeX on DartType {
/// Returns the display string of this type
/// without nullability suffix
String get nameWithoutSuffix {
final name = getDisplayString();
return name.endsWith('?') ? name.substring(0, name.length - 1) : name;
}
}
Loading

0 comments on commit 9aa237b

Please sign in to comment.