desktopPluginClassIsReal function

bool desktopPluginClassIsReal(
  1. String baseDir,
  2. String platform,
  3. String pluginClass
)

True when pluginClass is backed by a real implementation under <baseDir>/<platform>/ — i.e. the platform sources define the exact symbol Flutter's generated_plugin_registrant will call: windows → <PluginClass>RegisterWithRegistrar, linux → <snake_case(PluginClass)>_register_with_registrar. A dangling templated class (issue #10) has no such symbol and must be stripped, or CMake fails with "No target <plugin>_plugin". A hand-written hybrid plugin (ffiPlugin: true PLUS pluginClass — e.g. FFI bindings with a texture-registrar plugin class) defines it, and stripping the entry silently empties the registrant at runtime (issue #23).

Implementation

bool desktopPluginClassIsReal(String baseDir, String platform, String pluginClass) {
  final dir = Directory(p.join(baseDir, platform));
  if (!dir.existsSync()) return false;
  final symbol = platform == 'windows' ? '${pluginClass}RegisterWithRegistrar' : '${_snakeCasePluginClass(pluginClass)}_register_with_registrar';
  final srcRe = RegExp(r'\.(c|cc|cpp|h|hpp)$');
  for (final f in dir.listSync(recursive: true, followLinks: false).whereType<File>()) {
    final path = f.path.replaceAll(r'\', '/');
    if (path.contains('/ephemeral/') || path.contains('/build/') || path.contains('/.symlinks/')) continue;
    if (!srcRe.hasMatch(path)) continue;
    try {
      if (f.readAsStringSync().contains(symbol)) return true;
    } catch (_) {
      // Unreadable/binary file — not the registrant source.
    }
  }
  return false;
}