purgeStaleCppKotlinRegistrations function

void purgeStaleCppKotlinRegistrations(
  1. List<ModuleInfo> cppModules, {
  2. String baseDir = '.',
})

Removes stale <Module>JniBridge.register(...) calls from Plugin.kt for modules that have been converted to NativeImpl.cpp.

When a user switches android: NativeImpl.kotlinAndroidNativeImpl.cpp (or any C++ variant), the old registration call is left as dead code that causes a Kotlin "Unresolved reference" compile error. This function finds and removes those stale calls automatically on every nitrogen link run.

Implementation

void purgeStaleCppKotlinRegistrations(
  List<ModuleInfo> cppModules, {
  String baseDir = '.',
}) {
  if (cppModules.isEmpty) return;
  final kotlinDir = Directory(
    p.join(baseDir, 'android', 'src', 'main', 'kotlin'),
  );
  if (!kotlinDir.existsSync()) return;
  final pluginFiles = kotlinDir
      .listSync(recursive: true, followLinks: false)
      .whereType<File>()
      .where((f) => !f.path.contains('.symlinks'))
      .where((f) => f.path.endsWith('Plugin.kt'))
      .toList();
  if (pluginFiles.isEmpty) return;
  final pluginFile = pluginFiles.first;
  var content = pluginFile.readAsStringSync();
  bool modified = false;

  for (final m in cppModules) {
    // Match: <Module>JniBridge.register(<anything>)
    // The line may have leading whitespace and optional trailing comment.
    final stalePattern = RegExp(
      r'[ \t]*' + RegExp.escape('${m.module}JniBridge') + r'\.register\(.*\)[ \t]*\r?\n?',
    );
    if (stalePattern.hasMatch(content)) {
      content = content.replaceAll(stalePattern, '');
      modified = true;
    }
  }

  // Clean up orphaned imports for the removed JniBridge class.
  for (final m in cppModules) {
    final importPattern = RegExp(
      r'import [^\n]+?' + RegExp.escape('${m.module}JniBridge') + r'[^\n]*\n?',
    );
    if (importPattern.hasMatch(content)) {
      content = content.replaceAll(importPattern, '');
      modified = true;
    }
  }

  if (modified) pluginFile.writeAsStringSync(content);
}