scanDirectory function

Future<Map<String, List<String>>> scanDirectory(
  1. String directoryPath, {
  2. List<String>? excludePatterns,
})

Scan directory function with REGEX-based string extraction.

Entry point that uses pattern matching for string extraction. This function is optimized for reliable and fast extraction.

Parameters:

  • directoryPath - The root directory to scan for Dart files
  • excludePatterns - Optional list of glob patterns to exclude files/directories

Returns a Map where keys are file paths and values are lists of extracted strings. All strings are validated using pattern matching and context analysis.

Example:

final results = await scanDirectory('/path/to/flutter/project');

Implementation

Future<Map<String, List<String>>> scanDirectory(String directoryPath,
    {List<String>? excludePatterns}) async {
  print('🤖 Using pattern-based extraction...');
  // Initialize string extractor
  await StringExtractorFactory.initializeML();
  print(
      '🎯 Extractor Status: ${StringExtractorFactory.isMLInitialized ? 'Ready' : 'Failed to initialize'}');

  // Log directory path for debugging
  final currentDir = Directory.current.path;
  print('Current working directory: $currentDir');
  print('Scanning directory (input path): "$directoryPath"');

  // Normalize directory path (this is critical for handling the command name issue)
  String normalizedPath = directoryPath;

  // Hard safety check: if the path is a command name, replace it with "lib"
  if (normalizedPath == 'internationalize' || normalizedPath == 'i18n') {
    normalizedPath = 'lib';
    print('WARNING: Command name detected as path, replaced with "lib"');
  }

  // Convert relative path to absolute path if needed using path package
  if (!path.isAbsolute(normalizedPath)) {
    normalizedPath = path.join(currentDir, normalizedPath);
    print('Converted to absolute path: "$normalizedPath"');
  }

  // Normalize the final path
  normalizedPath = path.normalize(normalizedPath);

  print('Final normalized path to scan: "$normalizedPath"');

  // Verify the directory exists
  final directory = Directory(normalizedPath);
  if (!directory.existsSync()) {
    final error = 'Directory does not exist: "$normalizedPath"';
    print('ERROR: $error');
    throw FileSystemException(error, normalizedPath);
  }

  // If no exclude patterns provided, try to load from preferences
  if (excludePatterns == null) {
    try {
      final prefs = PreferencesManager.loadPreferences();
      if (prefs.containsKey('excludePatterns')) {
        final patterns = prefs['excludePatterns'];
        if (patterns is List) {
          excludePatterns = patterns.cast<String>();
        }
      }
    } catch (e) {
      // Just use default patterns if preferences can't be loaded
      print(
          '\u001b[33mWarning: Could not load exclude patterns from preferences: $e\u001b[0m');
    }
  }

  try {
    var scanner = FileScanner(directory.path);
    var dartFiles = scanner.scan();
    var result = <String, List<String>>{};

    print('Found ${dartFiles.length} Dart files.');
    print('Scanning files for translatable strings...');

    // Display overall summary progress
    print(
        'Processing ${dartFiles.length} files with cache-based incremental extraction...');

    // Use cache-aware parallel extraction for all dartFiles
    final batchResults = await _extractFromFilesWithCache(
        dartFiles, directory.path,
        maxParallelOperations: 10);
    result.addAll(batchResults);

    return result;
  } catch (e) {
    throw FileSystemException(
        'Error scanning directory: ${e.toString()}', directoryPath);
  }
}