generateDefaultsProvider static method
String
generateDefaultsProvider(
- Element element,
- bool createBaseClass
)
Implementation
static String generateDefaultsProvider(
Element element, bool createBaseClass) {
if (element is EnumElement) return '';
final classElement = element.asClassElement();
final superTypeElement = classElement.supertype!.element;
final superTypeAnnotation = TypeChecker.fromRuntime(DefaultsProvider)
.firstAnnotationOf(superTypeElement);
final superClassConstructorFields = _getFieldDescriptors(superTypeElement,
'Object' != superTypeElement.displayName);
final superClassHasDefaultsProvider = superTypeAnnotation != null &&
superClassConstructorFields.isNotEmpty;
final className = classElement.name;
final constructorFields = _getFieldDescriptors(classElement, true);
final parameterFieldBuffer = StringBuffer();
final constructorFieldBuffer = StringBuffer();
// let's get all the constructors which cover all non-nullable final fields
final missingFields = <String>{};
final constructors = classElement.getConstructorsMatchingFields(
fieldDescriptors: constructorFields,
allowMissingFields: true,
missingFields: missingFields);
// let's just pick the first of the valid constructors
final classConstructor = constructors.isEmpty
? throw InvalidGenerationSourceError(
'Cannot generate defaults provider for class ${classElement.name} because '
'it is missing a constructor that covers all final properties.\n'
'\tMissing fields: $missingFields')
: constructors.first;
_buildConstructorBuffer(classConstructor, [...constructorFields],
constructorFieldBuffer, createBaseClass);
for (var field in constructorFields) {
final fieldTypeName = field.fieldElementTypeName == 'dynamic'
? field.fieldElementTypeName
: '${field.fieldElementTypeName}?';
parameterFieldBuffer.writeln('$fieldTypeName ${field.displayName},');
}
final propertyFields = _getFieldDescriptors(classElement, false);
final propertyFieldBuffer = StringBuffer();
for (var field in constructorFields) {
if (!superClassHasDefaultsProvider ||
propertyFields
.any((element) => element.displayName == field.displayName)) {
var gen =
FieldCodeGenerator.fromFieldDescriptor(field, createBaseClass);
propertyFieldBuffer.writeln(
'''${field.fieldElementTypeName} get ${field.displayName} ${createBaseClass && gen.defaultExpression == '' ? '' : ' => ${gen.defaultExpression}'};''');
} else {
propertyFieldBuffer.writeln(
'''${field.fieldElementTypeName} get ${field.displayName} => _superDefaultsProvider.${field.displayName};''');
}
}
final providerClassName =
'\$${className}DefaultsProvider${createBaseClass ? 'Base' : ''}';
final superDeclaration = superClassHasDefaultsProvider
? '''static const _superDefaultsProvider = \$${superTypeElement.name}DefaultsProvider();'''
: '';
final constructorName = classConstructor.name.isNotEmpty
? '$className.${classConstructor.name}'
: className;
final constructor = classElement.isAbstract
? ''
: '''
$className createWithDefaults( ${parameterFieldBuffer.isEmpty ? '' : '{ $parameterFieldBuffer }'} ) {
return $constructorName(
$constructorFieldBuffer
);
}
''';
return '''
${createBaseClass ? 'abstract' : ''} class $providerClassName {
const $providerClassName();
$superDeclaration
$constructor
$propertyFieldBuffer
}
''';
}