generateForAnnotatedElement method

  1. @override
Future<String> generateForAnnotatedElement(
  1. Element element,
  2. ConstantReader annotation,
  3. BuildStep buildStep
)

Implement to return source code to generate for element.

This method is invoked based on finding elements annotated with an instance of T. The annotation is provided as a ConstantReader.

Supported return values include a single String or multiple String instances within an Iterable or Stream. It is also valid to return a Future of String, Iterable, or Stream.

Implementations should return null when no content is generated. Empty or whitespace-only String instances are also ignored.

Implementation

@override
Future<String> generateForAnnotatedElement(
  Element element,
  ConstantReader annotation,
  BuildStep buildStep,
) async {
  // Check if [@InferFromJsonFile] annotation is used on type alias element.
  // If not, throw an exception.
  if (element is! TypeAliasElement) {
    throw InvalidGenerationSourceError(
      '`@InferFromJsonFile` can only be used on type aliases.',
      element: element,
    );
  }

  // The type aliasing is performed using `typedef <TypeName> = <dynamic>;`.
  // Get the [TypeName] and use it as a generated class name - e.g.
  // `Inferred<TypeName>`.
  final className = element.name;

  // Read the [file] and [mergeStrategy] fields from annotation.
  late String jsonFilePath;
  try {
    jsonFilePath = annotation.read('file').stringValue;
  } on FormatException {
    throw InvalidGenerationSourceError(
      '`@InferFromJsonFile` path should not be null.',
      element: element,
    );
  }
  final mergeStrategy = getMergeStrategy(annotation);

  // Use [file] path to get [AssetId] object so we can read it using the
  // [BuildStep] object. The [file] path should be relative to current
  // file package.
  final jsonFileUri = Uri(path: jsonFilePath);
  final jsonAsset = AssetId.resolve(jsonFileUri, from: buildStep.inputId);

  // Read JSON file.
  final contents = await buildStep.readAsString(jsonAsset);

  // Infer object types and return generated Dart code.
  final result = inferObjectType(
    contents,
    className: className,
    mergeStrategy: mergeStrategy,
  );

  return result;
}