analyzeSymbolImpact method
ImpactResult
analyzeSymbolImpact({
- required List<
String> changedFiles, - List<
String> ? changedSymbolIds, - Duration analysisDuration = Duration.zero,
- bool isGitRepo = true,
- bool gitRequiresFallback = false,
- String? gitFallbackReason,
- bool isConservative = false,
- bool forceAll = false,
- bool hasAnalysisErrors = false,
- String? analysisErrorReason,
Implementation
ImpactResult analyzeSymbolImpact({
required List<String> changedFiles,
List<String>? changedSymbolIds,
Duration analysisDuration = Duration.zero,
bool isGitRepo = true,
bool gitRequiresFallback = false,
String? gitFallbackReason,
bool isConservative = false,
bool forceAll = false,
bool hasAnalysisErrors = false,
String? analysisErrorReason,
}) {
// If fallback is triggered at git or config level, run standard fallback
if (forceAll || !isGitRepo || gitRequiresFallback || hasAnalysisErrors) {
return fallbackFileAnalyzer.analyzeImpact(
changedFiles: changedFiles,
analysisDuration: analysisDuration,
isGitRepo: isGitRepo,
gitRequiresFallback: gitRequiresFallback,
gitFallbackReason: gitFallbackReason,
isConservative: isConservative,
forceAll: forceAll,
hasAnalysisErrors: hasAnalysisErrors,
analysisErrorReason: analysisErrorReason,
);
}
final testPaths = discoveredTests.map((t) => t.path).toList();
final allSymbols = symbolGraph.getAllSymbols();
// Determine changed symbols
final List<SymbolNode> changedSymbols = [];
if (changedSymbolIds != null && changedSymbolIds.isNotEmpty) {
for (final id in changedSymbolIds) {
final sym = symbolGraph.getSymbol(id);
if (sym != null) {
changedSymbols.add(sym);
} else {
// If a symbol ID was specified but not found in graph, construct transient symbol
final parts = id.split('#');
final file = parts.first;
final name = parts.length > 1 ? parts.last : id;
changedSymbols.add(SymbolNode(
id: id,
filePath: file,
symbolName: name,
symbolType: 'method',
));
}
}
} else {
for (final sym in allSymbols) {
if (changedFiles.contains(sym.filePath)) {
changedSymbols.add(sym);
}
}
}
// If no symbols resolved for changed dart files (or graph empty), fallback to file-level
final changedDartFiles = changedFiles.where((f) => f.endsWith('.dart')).toList();
if (symbolGraph.totalNodes == 0 || (changedDartFiles.isNotEmpty && changedSymbols.isEmpty)) {
return fallbackFileAnalyzer.analyzeImpact(
changedFiles: changedFiles,
analysisDuration: analysisDuration,
isGitRepo: isGitRepo,
gitRequiresFallback: gitRequiresFallback,
gitFallbackReason: gitFallbackReason,
isConservative: isConservative,
forceAll: forceAll,
hasAnalysisErrors: hasAnalysisErrors,
analysisErrorReason: analysisErrorReason,
);
}
final Set<String> affectedTestPaths = {};
final List<SymbolImpactPath> impactPaths = [];
final List<AffectedTestReason> affectedReasons = [];
for (final changedSym in changedSymbols) {
final dependents = symbolGraph.getTransitiveDependents(changedSym.id);
for (final entry in dependents.entries) {
final dependentId = entry.key;
final chain = entry.value;
final dependentNode = symbolGraph.getSymbol(dependentId);
if (dependentNode != null && (dependentNode.isTest || dependentNode.filePath.startsWith('test/'))) {
affectedTestPaths.add(dependentNode.filePath);
final path = SymbolImpactPath(
testPath: dependentNode.filePath,
changedSymbol: changedSym.symbolName,
targetSymbol: dependentNode.symbolName,
symbolChain: chain,
);
impactPaths.add(path);
affectedReasons.add(AffectedTestReason(
testPath: dependentNode.filePath,
dependencyChain: [changedSym.symbolName, ...chain],
));
}
}
}
final Map<String, AffectedTestReason> uniqueAffected = {};
for (final r in affectedReasons) {
uniqueAffected[r.testPath] = r;
}
final unaffectedTests = testPaths.where((t) => !affectedTestPaths.contains(t)).toList();
unaffectedTests.sort();
final modeStr = isConservative ? 'conservative' : 'default';
return ImpactResult(
changedFiles: changedFiles,
affectedTests: uniqueAffected.values.toList(),
unaffectedTests: unaffectedTests,
totalTests: testPaths.length,
analysisDuration: analysisDuration,
status: 'safe',
mode: modeStr,
isFallback: false,
fallbackReason: null,
fallbackExplanation: null,
analysisLevel: 'symbol',
changedSymbols: changedSymbols.map((s) => s.symbolName).toList(),
impactPaths: impactPaths,
);
}