generate method

  1. @override
Future<List<LibraryDeclaration>> generate(
  1. List<File> dartFiles
)
override

Generates both reflection metadata and concrete reflector classes.

This is the main entry point that processes all libraries in the mirror system (plus any force-loaded mirrors) and generates complete reflection metadata.

Parameters:

  • dartFiles: A list of Dart files to process via analyzer

Returns: A list of LibraryDeclaration objects representing the reflected libraries

Example:

final libraries = await generator.generate(dartFiles);
for (final library in libraries) {
  print('Library: ${library.uri}');
  for (final declaration in library.declarations) {
    print(' - ${declaration.name}');
  }
}

Implementation

@override
Future<List<LibraryDeclaration>> generate(List<File> dartFiles) async {
  // Initialize analyzer
  await _initializeAnalyzer(dartFiles);

  // Initialize tree shaker if needed
  if (configuration.enableTreeShaking) {
    _treeShaker = TreeShaker();
  }

  // Create package lookup
  for (final package in packages) {
    _packageCache[package.getName()] = package;
  }

  final libraries = <LibraryDeclaration>[];

  onInfo('Generating declaration metadata with analyzer integration...');

  for (final libraryMirror in loader) {
    final fileUri = libraryMirror.uri;

    try {
      final mustSkip = "jetleaf_lang/src/runtime/";
      if(libraryMirror.uri.toString() == "dart:mirrors" || libraryMirror.uri.toString().startsWith("package:$mustSkip") || libraryMirror.uri.toString().contains(mustSkip)) {
        continue;
      }

      onInfo('Processing library: ${fileUri.toString()}');
      LibraryDeclaration? libDecl;

      if (_isBuiltInDartLibrary(fileUri)) {
        // Handle built-in Dart libraries (dart:core, dart:io, etc.)
        libDecl = await _generateBuiltInLibraryDeclaration(libraryMirror);
      } else {
        // Handle user libraries and package libraries
        if (await shouldNotIncludeLibrary(fileUri, configuration) || isSkippableJetLeafPackage(fileUri)) {
          continue;
        }

        String? fileContent;
        try {
          fileContent = await _readSourceCode(fileUri);
          if ((isTest(fileContent) && configuration.skipTests) || hasMirrorImport(fileContent)) {
            continue;
          }
        } catch (e) {
          onError('Could not read file content for $fileUri: $e');
          continue;
        }

        libDecl = await generateLibrary(libraryMirror);
      }

      libraries.add(libDecl);
      _libraryCache[fileUri.toString()] = libDecl;
    } catch (e, stackTrace) {
      onError('Error processing library ${fileUri.toString()}: $e\n$stackTrace');
    }
  }

  // Apply tree-shaking if enabled
  Set<String> usedClasses = {};
  if (configuration.enableTreeShaking && _treeShaker != null) {
    final userPackageNames = packages
        .where((p) => p.getIsRootPackage())
        .map((p) => p.getName())
        .toSet();

    usedClasses = _treeShaker!.shake(libraries, userPackageNames);
    onInfo('Tree-shaking enabled: ${usedClasses.length} classes marked as used');
  }

  // Write declarations to files if configured
  if (configuration.writeDeclarationsToFiles) {
    _fileWriter = DeclarationFileWriter(configuration.outputPath);
    await _fileWriter!.writeDeclarations(libraries, usedClasses, configuration.enableTreeShaking);
    onInfo('Declarations written to ${configuration.outputPath}/classes/');
  }

  // Check for unresolved generic classes
  final unresolvedClasses = libraries
    .where((l) => l.getIsPublic() && !l.getIsSynthetic() && l.getPackage().getIsRootPackage())
    .flatMap((l) => l.getDeclarations())
    .whereType<TypeDeclaration>()
    .where((d) => GenericTypeParser.shouldCheckGeneric(d.getType()) && d.getIsPublic() && !d.getIsSynthetic());

  if (unresolvedClasses.isNotEmpty) {
    final warningMessage = '''
⚠️ Generic Class Discovery Issue ⚠️
Found ${unresolvedClasses.length} classes with unresolved runtime types:
${unresolvedClasses.map((d) => "• ${d.getSimpleName()} (${d.getQualifiedName()})").join("\n")}

These classes may need manual type resolution or have complex generic constraints.
    ''';
    onWarning(warningMessage);
  }

  return libraries;
}