findSymbol method
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;
}