linkMacosSwiftPlugin function
void
linkMacosSwiftPlugin(})
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);
}