findSymbol method

Future<List<SymbolMatch>> findSymbol(
  1. String name, {
  2. SymbolKind? kind,
  3. String? rootDir,
})

Find symbol definitions matching name.

This performs a regex-based heuristic scan for common declaration patterns. For precise results, prefer LSP-based symbol search.

Implementation

Future<List<SymbolMatch>> findSymbol(
  String name, {
  SymbolKind? kind,
  String? rootDir,
}) async {
  final root = rootDir ?? projectRoot;
  final dartFiles = await findFiles('*.dart', rootDir: root);
  final results = <SymbolMatch>[];

  // Patterns for common Dart declarations.
  final patterns = <SymbolKind, RegExp>{
    SymbolKind.classType: RegExp(
      r'^\s*(?:abstract\s+)?class\s+(' + _escRe(name) + r')\b',
    ),
    SymbolKind.function: RegExp(
      r'^\s*\w[\w<>,\s]*\s+(' + _escRe(name) + r')\s*\(',
    ),
    SymbolKind.enumType: RegExp(r'^\s*enum\s+(' + _escRe(name) + r')\b'),
    SymbolKind.variable: RegExp(
      r'^\s*(?:final|var|const|late)\s+\w+\s+(' + _escRe(name) + r')\b',
    ),
    SymbolKind.typeAlias: RegExp(r'^\s*typedef\s+(' + _escRe(name) + r')\b'),
  };

  // Filter to requested kind if specified.
  final Map<SymbolKind, RegExp?> activePatterns;
  if (kind != null && patterns.containsKey(kind)) {
    activePatterns = {kind: patterns[kind]};
  } else {
    activePatterns = patterns;
  }

  for (final filePath in dartFiles) {
    String content;
    try {
      content = await File(filePath).readAsString();
    } catch (_) {
      continue;
    }

    final lines = content.split('\n');
    String? currentContainer;

    for (var i = 0; i < lines.length; i++) {
      // Track containing class/enum.
      final classMatch = RegExp(
        r'^\s*(?:abstract\s+)?class\s+(\w+)',
      ).firstMatch(lines[i]);
      if (classMatch != null) currentContainer = classMatch.group(1);

      for (final entry in activePatterns.entries) {
        final re = entry.value;
        if (re == null) continue;
        final m = re.firstMatch(lines[i]);
        if (m != null) {
          results.add(
            SymbolMatch(
              name: m.group(1)!,
              kind: entry.key,
              file: filePath,
              line: i + 1,
              containerName: entry.key != SymbolKind.classType
                  ? currentContainer
                  : null,
            ),
          );
        }
      }
    }
  }
  return results;
}