build method
- BuildStep buildStep
override
Generates the outputs for a given BuildStep.
Implementation
@override
Future<void> build(BuildStep buildStep) async {
log.info("Starting Firestorm Builder for ${buildStep.inputId}...");
//Buffers:
final fileBuffer = StringBuffer();
final headerBuffer = StringBuffer();
final importsBuffer = StringBuffer();
final classBuffer = StringBuffer();
final converterBuffer = StringBuffer();
//Generate header
HeaderGenerator.generateHeader(headerBuffer);
importsBuffer.writeln("import 'package:firestorm/fs/fs.dart';");
importsBuffer.writeln("import 'package:firestorm/rdb/rdb.dart';");
importsBuffer.writeln("import 'package:firestorm/ls/ls.dart';");
final Map<AssetId, Iterable<ClassElement>> allClasses = {};
final Map<ClassElement, AssetId> assetIDs = {};
final Map<EnumElement, AssetId> enumAssetIds = {};
//Read the classes from the files and store in allClasses map:
await for (final input in buildStep.findAssets(Glob('lib/**.dart'))) { //iterates through all .dart files
if (!await buildStep.resolver.isLibrary(input)) {
continue;
}
final libraryElement = await buildStep.resolver.libraryFor(input);
final libraryReader = LibraryReader(libraryElement);
allClasses[input] = libraryReader.classes;
for (final aClass in libraryReader.classes) {
assetIDs[aClass] = input; //Map each class to its AssetId
}
//enums:
for (final aClass in libraryReader.enums) {
enumAssetIds[aClass] = input; //Map each enum to its AssetId
}
}
//Perform filtering
//1. @FirestormObject annotation
//2. public no-arg constructor
//3. ID field
//4. Firestore or Realtime Database support (type checks)
ValidClassHolder validClassHolder = ValidClassHolder.empty();
for (final pair in allClasses.entries) {
final Iterable<ClassElement> allClasses = pair.value;
var fileClassHolder = ClassChecker.filter(allClasses);
validClassHolder.join(fileClassHolder);
}
if (validClassHolder.getAllValidClasses().isEmpty) {
log.info("No valid classes found for Firestorm:");
print("""
INSTRUCTIONS
--------------------------------------------------------------------
1. Use the @FirestormObject() annotation in your data classes.
2. Ensure your data classes have a public constructor.
3. Ensure your data classes have an 'id' field of type String.
4. Ensure your data classes only use supported types for Firestore or Realtime Database.
5. Ensure that any private fields have both a getter and setter method.
More information: https://github.com/RayLabz/Firestorm/blob/master/firestorm_flutter/defining-classes.md""");
return;
}
//For every valid class, generate necessary imports and its extension:
for (final validClass in validClassHolder.getAllValidClasses()) {
//Add into the import buffer, if there are any classes in this file
ImportGenerator.generateImports(importsBuffer, assetIDs[validClass]!);
//Generate extensions:
ExtensionGenerator.generateExtension(
classBuffer,
validClass,
validClassHolder.hasFSSupport(validClass),
validClassHolder.hasRDBSupport(validClass)
);
}
//Generate imports for enums:
for (final assetID in enumAssetIds.values) {
ImportGenerator.generateImports(importsBuffer, assetID);
}
//Generate import for firestore library:
// ImportGenerator.generateImportFromString(importsBuffer, "package:cloud_firestore/cloud_firestore.dart");
//Generate the converter functions
RegistryGenerator.generateConverterFunctions(converterBuffer, validClassHolder);
//Add everything into the file buffer
fileBuffer.writeln(headerBuffer.toString());
fileBuffer.writeln(importsBuffer.toString());
fileBuffer.writeln(classBuffer.toString());
fileBuffer.writeln(converterBuffer.toString());
final formattedOutput = fileBuffer.toString();
final outputId = AssetId(buildStep.inputId.package, 'lib/generated/firestorm_models.dart');
await buildStep.writeAsString(outputId, formattedOutput);
log.info("Firestorm Builder completed for ${buildStep.inputId}. Generated file: $outputId.");
}