executeImpl method

  1. @override
Future executeImpl(
  1. Map<String, dynamic> params
)
override

Implement the actual tool logic

params are the validated parameters (never null here) Returns the result data to send in the response

Implementation

@override
Future<dynamic> executeImpl(Map<String, dynamic> params) async {
  final query = params['query'] as String;
  final filePattern = params['file_pattern'] as String? ?? '*.dart';
  final searchPath = params['path'] as String?;
  final caseSensitive = params['case_sensitive'] as bool? ?? false;
  final useRegex = params['use_regex'] as bool? ?? false;
  final maxResults = params['max_results'] as int? ?? 50;
  // TODO: Implement context_lines feature
  // final contextLines = params['context_lines'] as int? ?? 0;
  final excludePatterns = params['exclude_patterns'] as List<String>?;

  final project = ServerPodLocator.getProject();
  if (project == null || !project.isValid) {
    return {'error': 'Not a valid ServerPod project'};
  }

  // Determine search directory
  String basePath = project.rootPath;
  if (searchPath != null && searchPath.isNotEmpty) {
    basePath = p.normalize(p.join(project.rootPath, searchPath));
  }

  final baseDir = Directory(basePath);
  if (!baseDir.existsSync()) {
    return {
      'error': 'Search path not found',
      'path': basePath,
    };
  }

  // Build regex for matching
  RegExp searchRegex;
  try {
    if (useRegex) {
      searchRegex = RegExp(query, caseSensitive: caseSensitive);
    } else {
      searchRegex = RegExp(
        RegExp.escape(query),
        caseSensitive: caseSensitive,
      );
    }
  } catch (e) {
    return {
      'error': 'Invalid query pattern',
      'message': e.toString(),
    };
  }

  // Search files
  final results = <CodeMatch>[];
  final filesSearched = <String>[];

  await for (final entity in _findFiles(baseDir, filePattern, excludePatterns)) {
    if (results.length >= maxResults) break;

    final file = entity as File;
    filesSearched.add(file.path);

    final matches = await _searchInFile(
      file,
      project.rootPath,
      searchRegex,
      maxResults - results.length,
    );

    results.addAll(matches);
  }

  return {
    'query': query,
    'filePattern': filePattern,
    'searchPath': basePath,
    'caseSensitive': caseSensitive,
    'useRegex': useRegex,
    'results': results.map((m) => m.toJson()).toList(),
    'resultCount': results.length,
    'filesSearched': filesSearched.length,
    'truncated': results.length >= maxResults,
  };
}