using System.IO;
using System.Linq;
using System.Collections.Generic;
using IntelligentProjectAnalyzer.Analyzer;
// All using statements now refer to the new data-only class
using static IntelligentProjectAnalyzer.Editor.DependencyBuilderData;
namespace IntelligentProjectAnalyzer.Editor
{
///
/// Executes the CPU-intensive analysis on a background thread to avoid freezing the editor.
///
public static class BackgroundAnalyzer
{
///
/// Runs the full dependency analysis on a collection of assets.
///
/// A list containing metadata for all assets to be analyzed.
/// The setup data required for Roslyn analysis.
/// A list of analysis results, one for each processed asset.
public static List RunAnalysis(List allMetadata, RoslynSetupData roslynSetupData)
{
// Initialize the Roslyn analyzer with all the necessary data.
var roslynAnalyzer = new RoslynTypeDependencyAnalyzer(roslynSetupData.SourceFiles, roslynSetupData.References, roslynSetupData.PreprocessorSymbols, roslynSetupData.SystemTypePrefixes);
// --- IMPORTANT ---
// First, run analysis on ALL script types to build the complete, internal dependency tree in the analyzer.
var allScriptTypes = roslynAnalyzer.TypeToPathMap.Keys;
roslynAnalyzer.AnalyzeTypeDependenciesForFile(allScriptTypes);
// Now, iterate through our assets and populate the script dependencies.
foreach (var metadata in allMetadata)
{
// We only need to run Roslyn analysis for scripts.
// Prefabs and SOs have their direct dependencies already.
if (metadata is ScriptMetadata scriptMetadata)
{
ProcessScript(scriptMetadata, roslynAnalyzer, roslynSetupData.TypeToGuidMap);
}
}
return allMetadata;
}
///
/// Processes a single script to find all its recursive dependencies.
///
private static void ProcessScript(ScriptMetadata metadata, RoslynTypeDependencyAnalyzer analyzer, IReadOnlyDictionary typeToGuidMap)
{
// Get all types defined within this specific script file.
var typesInFile = analyzer.TypeToPathMap
.Where(pair => Path.GetFullPath(pair.Value).Replace('\\', '/') == metadata.FullPath)
.Select(pair => pair.Key);
var allDependenciesInFile = new HashSet();
foreach (var typeName in typesInFile)
{
// For each type, get its complete, recursive list of dependencies from the analyzer's pre-built tree.
var dependenciesForType = analyzer.GetRecursiveDependencies(typeName);
foreach (var dep in dependenciesForType)
{
allDependenciesInFile.Add(dep);
}
}
// Now, convert the dependency type names back to GUIDs and add them to the metadata object.
foreach (var depName in allDependenciesInFile)
{
if (typeToGuidMap.TryGetValue(depName, out var depGuid) && !string.IsNullOrEmpty(depGuid) && !metadata.DependencyGuids.Contains(depGuid))
{
metadata.DependencyGuids.Add(depGuid);
}
}
}
}
}