emitInspection function

String emitInspection(
  1. InspectionCache cache, {
  2. required AppType appType,
  3. bool primaryModuleOnly = true,
  4. String moduleParentPrefix = "",
})

Emits Dart source code of the generated interface definitions.

The returned String is a valid Dart source file. It should be written to a file with the .g.dart extension and formatted with dart format.

The appType parameter is used to determine which Python FFI package to import.

If primaryModuleOnly is true, only the primary module will be emitted. Otherwise, all found modules will have their module definition included.

The moduleParentPrefix parameter is used to prefix the module name of every module. This is useful for nested modules.

Implementation

String emitInspection(
  InspectionCache cache, {
  required AppType appType,
  bool primaryModuleOnly = true,
  String moduleParentPrefix = "",
}) {
  final Module? primaryModule = cache.modules.firstOrNull;
  final InstantiatedModule? primaryInstantiatedModule = primaryModule != null
      ? InstantiatedModule.fromModule(primaryModule)
      : null;
  if (primaryInstantiatedModule == null) {
    primaryModuleOnly = false;
  }
  const String analysisIgnoreLine =
      "// ignore_for_file: camel_case_types, non_constant_identifier_names, prefer_void_to_null";
  final StringBuffer buffer = StringBuffer("""
$analysisIgnoreLine

""");
  if (primaryInstantiatedModule != null) {
    buffer.writeln("library ${primaryInstantiatedModule.sanitizedName};");
  }
  const String typedDataImportLine = 'import "dart:typed_data";';
  const String pythonFfiConsoleImportLine =
      'import "package:python_ffi_dart/python_ffi_dart.dart";';
  const String pythonFfiFlutterImportLine =
      'import "package:python_ffi/python_ffi.dart";';
  final String pythonFfiImportLine = switch (appType) {
    AppType.console => pythonFfiConsoleImportLine,
    AppType.flutter => pythonFfiFlutterImportLine,
  };
  buffer.writeln("""
$typedDataImportLine

$pythonFfiImportLine
""");
  final Set<String> topLevelNames = <String>{};
  for (final ClassInstance typedef in cache.typedefs) {
    for (final InstantiatedClassInstance instantiatedTypedef
        in typedef.instantiations.whereType()) {
      final String typedefName = instantiatedTypedef.sanitizedName;
      if (topLevelNames.contains(typedefName)) {
        continue;
      }
      topLevelNames.add(typedefName);
      instantiatedTypedef.emit(
        buffer,
        cache: cache,
        appType: appType,
      );
    }
  }
  for (final ClassDefinition classDefinition in cache.classDefinitions) {
    for (final InstantiatedClassDefinition instantiatedClassDefinition
        in classDefinition.instantiations.whereType()) {
      final String className = instantiatedClassDefinition.sanitizedName;
      if (topLevelNames.contains(className)) {
        continue;
      }
      topLevelNames.add(className);
      instantiatedClassDefinition.emit(
        buffer,
        cache: cache,
        appType: appType,
        moduleParentPrefix: moduleParentPrefix,
      );
    }
  }
  for (final Module module in cache.modules) {
    final InstantiatedModule instantiatedModule =
        InstantiatedModule.fromModule(module);
    final String moduleName = instantiatedModule.sanitizedName;
    if (topLevelNames.contains(moduleName)) {
      continue;
    }
    topLevelNames.add(moduleName);
    instantiatedModule.emit(
      buffer,
      cache: cache,
      appType: appType,
      moduleParentPrefix: moduleParentPrefix,
    );
  }
  final String result = buffer.toString();
  if (!result.contains("Uint8List")) {
    return result.replaceAll(typedDataImportLine, "");
  }
  return result;
}