linkMacosSwiftPlugin function

void linkMacosSwiftPlugin(
  1. String pluginName,
  2. List<Map<String, String>> modules, {
  3. String baseDir = '.',
})

Wires non-cpp module registrations into the macOS Swift plugin file.

Mirrors linkSwiftPlugin but targets macos/ instead of ios/. Searches macos/ recursively for *Plugin.swift and injects Registry.register(...) calls for each non-cpp module that doesn't already have one.

Implementation

void linkMacosSwiftPlugin(String pluginName, List<Map<String, String>> modules, {String baseDir = '.'}) {
  final macosDir = Directory(p.join(baseDir, 'macos'));
  if (!macosDir.existsSync()) return;
  final pluginFiles = macosDir
      .listSync(recursive: true, followLinks: false)
      .whereType<File>()
      .where((f) => !f.path.contains('.symlinks'))
      .where((f) => f.path.endsWith('Plugin.swift'))
      .toList();

  if (pluginFiles.isEmpty) {
    // Create default macOS plugin if missing
    final className = _toPascalCase(pluginName);
    final fileName = '${className}Plugin.swift';
    final targetPath = p.join(macosDir.path, 'Classes', fileName);
    Directory(p.dirname(targetPath)).createSync(recursive: true);
    final stub =
        '''import FlutterMacOS
import Foundation

public class ${className}Plugin: NSObject, FlutterPlugin {
  public static func register(with registrar: FlutterPluginRegistrar) {
    // Nitro registration will be injected here by nitrogen link.
  }
}
''';
    File(targetPath).writeAsStringSync(stub);
    pluginFiles.add(File(targetPath));
  }

  final pluginFile = pluginFiles.first;
  var content = pluginFile.readAsStringSync();
  bool modified = false;
  for (final m in modules) {
    final name = m['module']!;
    final lib = (m['lib'] ?? name.toLowerCase()).replaceAll('-', '_');
    final reg = '${name}Registry';
    // Standard implementation naming: BenchmarkImpl or BenchmarkModuleImpl
    final impl = name.endsWith('Module') ? '${name}Impl' : '${name}ModuleImpl';

    // ── 1. Ensure import is present ─────────────────────────────────────────
    final importLine = 'import nitro_${lib}_module';
    if (!content.contains(importLine)) {
      // Insert after the last 'import …' line
      final importMatches = RegExp(r'^import .+$', multiLine: true).allMatches(content);
      if (importMatches.isNotEmpty) {
        final lastImport = importMatches.last;
        content = content.replaceRange(lastImport.end, lastImport.end, '\n$importLine');
      } else {
        content = '$importLine\n\n$content';
      }
      modified = true;
    }

    // ── 2. Ensure register() call is present ────────────────────────────────
    if (!content.contains('$reg.register')) {
      content = content.replaceFirst(
        'public static func register(with registrar: FlutterPluginRegistrar) {',
        'public static func register(with registrar: FlutterPluginRegistrar) {\n    $reg.register($impl())',
      );
      modified = true;
    }
  }
  if (modified) pluginFile.writeAsStringSync(content);
}