add new file v2

This commit is contained in:
Matt Parker
2025-10-19 20:47:59 +10:00
parent 5e1f1dfdd6
commit b180f82b1f
8 changed files with 37 additions and 18 deletions

View File

@@ -745,7 +745,7 @@ public class RoslynAnalysis
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(AddDocument)}"); using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(AddDocument)}");
await _solutionLoadedTcs.Task; await _solutionLoadedTcs.Task;
Guard.Against.Null(fileModel, nameof(fileModel)); Guard.Against.Null(fileModel, nameof(fileModel));
Guard.Against.NullOrEmpty(content, nameof(content)); Guard.Against.Null(content, nameof(content));
var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == ((IChildSharpIdeNode)fileModel).GetNearestProjectNode()!.FilePath); var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == ((IChildSharpIdeNode)fileModel).GetNearestProjectNode()!.FilePath);

View File

@@ -23,6 +23,19 @@ public class IdeFileExternalChangeHandler
if (sharpIdeFile == null) if (sharpIdeFile == null)
{ {
// If sharpIdeFile is null, it means the file was created externally, and we need to create it and add it to the solution model // If sharpIdeFile is null, it means the file was created externally, and we need to create it and add it to the solution model
var createdFileDirectory = Path.GetDirectoryName(filePath)!;
// TODO: Handle being contained by a project directly
//var containingProject = SolutionModel.AllProjects.SingleOrDefault(p => createdFileDirectory == Path.GetDirectoryName(p.FilePath));
var containingFolder = SolutionModel.AllFolders.SingleOrDefault(f => f.Path == createdFileDirectory);
if (containingFolder is null)
{
// TODO: Create the folder and add it to the solution model
}
sharpIdeFile = new SharpIdeFile(filePath, Path.GetFileName(filePath), containingFolder, []);
containingFolder.Files.Add(sharpIdeFile);
SolutionModel.AllFiles.Add(sharpIdeFile);
// sharpIdeFile = TODO; // sharpIdeFile = TODO;
} }
Guard.Against.Null(sharpIdeFile, nameof(sharpIdeFile)); Guard.Against.Null(sharpIdeFile, nameof(sharpIdeFile));

View File

@@ -73,7 +73,9 @@ public sealed class IdeFileWatcher : IDisposable
private void HandleCreated(string fullPath) private void HandleCreated(string fullPath)
{ {
Console.WriteLine($"FileSystemWatcher: Created - {fullPath}"); if (Path.HasExtension(fullPath) is false) return; // we don't care about directory changes
//Console.WriteLine($"FileSystemWatcher: Created - {fullPath}");
GlobalEvents.Instance.FileSystemWatcherInternal.FileCreated.InvokeParallelFireAndForget(fullPath);
} }
// The only changed event we care about is files, not directories // The only changed event we care about is files, not directories

View File

@@ -14,13 +14,13 @@ public class SharpIdeFolder : ISharpIdeNode, IExpandableSharpIdeNode, IChildShar
public bool Expanded { get; set; } public bool Expanded { get; set; }
[SetsRequiredMembers] [SetsRequiredMembers]
public SharpIdeFolder(DirectoryInfo folderInfo, IExpandableSharpIdeNode parent, ConcurrentBag<SharpIdeFile> allFiles) public SharpIdeFolder(DirectoryInfo folderInfo, IExpandableSharpIdeNode parent, ConcurrentBag<SharpIdeFile> allFiles, ConcurrentBag<SharpIdeFolder> allFolders)
{ {
Parent = parent; Parent = parent;
Path = folderInfo.FullName; Path = folderInfo.FullName;
Name = folderInfo.Name; Name = folderInfo.Name;
Files = folderInfo.GetFiles(this, allFiles); Files = folderInfo.GetFiles(this, allFiles);
Folders = this.GetSubFolders(this, allFiles); Folders = this.GetSubFolders(this, allFiles, allFolders);
} }
public SharpIdeFolder() public SharpIdeFolder()

View File

@@ -10,7 +10,7 @@ public static class TreeMapperV2
return folder.Files return folder.Files
.Concat(folder.Folders.SelectMany(sub => sub.GetAllFiles())); .Concat(folder.Folders.SelectMany(sub => sub.GetAllFiles()));
} }
public static List<SharpIdeFolder> GetSubFolders(string csprojectPath, SharpIdeProjectModel sharpIdeProjectModel, ConcurrentBag<SharpIdeFile> allFiles) public static List<SharpIdeFolder> GetSubFolders(string csprojectPath, SharpIdeProjectModel sharpIdeProjectModel, ConcurrentBag<SharpIdeFile> allFiles, ConcurrentBag<SharpIdeFolder> allFolders)
{ {
var projectDirectory = Path.GetDirectoryName(csprojectPath)!; var projectDirectory = Path.GetDirectoryName(csprojectPath)!;
var rootFolder = new SharpIdeFolder var rootFolder = new SharpIdeFolder
@@ -21,12 +21,12 @@ public static class TreeMapperV2
Files = [], Files = [],
Folders = [] Folders = []
}; };
var subFolders = rootFolder.GetSubFolders(sharpIdeProjectModel, allFiles); var subFolders = rootFolder.GetSubFolders(sharpIdeProjectModel, allFiles, allFolders);
return subFolders; return subFolders;
} }
private static readonly string[] _excludedFolders = ["bin", "obj", "node_modules"]; private static readonly string[] _excludedFolders = ["bin", "obj", "node_modules"];
public static List<SharpIdeFolder> GetSubFolders(this SharpIdeFolder folder, IExpandableSharpIdeNode parent, ConcurrentBag<SharpIdeFile> allFiles) public static List<SharpIdeFolder> GetSubFolders(this SharpIdeFolder folder, IExpandableSharpIdeNode parent, ConcurrentBag<SharpIdeFile> allFiles, ConcurrentBag<SharpIdeFolder> allFolders)
{ {
var directoryInfo = new DirectoryInfo(folder.Path); var directoryInfo = new DirectoryInfo(folder.Path);
ConcurrentBag<SharpIdeFolder> subFolders = []; ConcurrentBag<SharpIdeFolder> subFolders = [];
@@ -47,8 +47,9 @@ public static class TreeMapperV2
Parallel.ForEach(subFolderInfos, subFolderInfo => Parallel.ForEach(subFolderInfos, subFolderInfo =>
{ {
var subFolder = new SharpIdeFolder(subFolderInfo, parent, allFiles); var subFolder = new SharpIdeFolder(subFolderInfo, parent, allFiles, allFolders);
subFolders.Add(subFolder); subFolders.Add(subFolder);
allFolders.Add(subFolder);
}); });
return subFolders.ToList(); return subFolders.ToList();

View File

@@ -36,9 +36,10 @@ public class SharpIdeSolutionModel : ISharpIdeNode, IExpandableSharpIdeNode
public required string FilePath { get; set; } public required string FilePath { get; set; }
public required string DirectoryPath { get; set; } public required string DirectoryPath { get; set; }
public required List<SharpIdeProjectModel> Projects { get; set; } public required List<SharpIdeProjectModel> Projects { get; set; }
public required List<SharpIdeSolutionFolder> Folders { get; set; } public required List<SharpIdeSolutionFolder> SlnFolders { get; set; }
public required HashSet<SharpIdeProjectModel> AllProjects { get; set; } public required HashSet<SharpIdeProjectModel> AllProjects { get; set; }
public required HashSet<SharpIdeFile> AllFiles { get; set; } public required HashSet<SharpIdeFile> AllFiles { get; set; }
public required HashSet<SharpIdeFolder> AllFolders { get; set; }
public bool Expanded { get; set; } public bool Expanded { get; set; }
[SetsRequiredMembers] [SetsRequiredMembers]
@@ -47,13 +48,15 @@ public class SharpIdeSolutionModel : ISharpIdeNode, IExpandableSharpIdeNode
var solutionName = Path.GetFileName(solutionFilePath); var solutionName = Path.GetFileName(solutionFilePath);
var allProjects = new ConcurrentBag<SharpIdeProjectModel>(); var allProjects = new ConcurrentBag<SharpIdeProjectModel>();
var allFiles = new ConcurrentBag<SharpIdeFile>(); var allFiles = new ConcurrentBag<SharpIdeFile>();
var allFolders = new ConcurrentBag<SharpIdeFolder>();
Name = solutionName; Name = solutionName;
FilePath = solutionFilePath; FilePath = solutionFilePath;
DirectoryPath = Path.GetDirectoryName(solutionFilePath)!; DirectoryPath = Path.GetDirectoryName(solutionFilePath)!;
Projects = intermediateModel.Projects.Select(s => new SharpIdeProjectModel(s, allProjects, allFiles, this)).ToList(); Projects = intermediateModel.Projects.Select(s => new SharpIdeProjectModel(s, allProjects, allFiles, allFolders, this)).ToList();
Folders = intermediateModel.SolutionFolders.Select(s => new SharpIdeSolutionFolder(s, allProjects, allFiles, this)).ToList(); SlnFolders = intermediateModel.SolutionFolders.Select(s => new SharpIdeSolutionFolder(s, allProjects, allFiles, allFolders, this)).ToList();
AllProjects = allProjects.ToHashSet(); AllProjects = allProjects.ToHashSet();
AllFiles = allFiles.ToHashSet(); AllFiles = allFiles.ToHashSet();
AllFolders = allFolders.ToHashSet();
} }
} }
public class SharpIdeSolutionFolder : ISharpIdeNode, IExpandableSharpIdeNode, IChildSharpIdeNode public class SharpIdeSolutionFolder : ISharpIdeNode, IExpandableSharpIdeNode, IChildSharpIdeNode
@@ -66,13 +69,13 @@ public class SharpIdeSolutionFolder : ISharpIdeNode, IExpandableSharpIdeNode, IC
public required IExpandableSharpIdeNode Parent { get; set; } public required IExpandableSharpIdeNode Parent { get; set; }
[SetsRequiredMembers] [SetsRequiredMembers]
internal SharpIdeSolutionFolder(IntermediateSlnFolderModel intermediateModel, ConcurrentBag<SharpIdeProjectModel> allProjects, ConcurrentBag<SharpIdeFile> allFiles, IExpandableSharpIdeNode parent) internal SharpIdeSolutionFolder(IntermediateSlnFolderModel intermediateModel, ConcurrentBag<SharpIdeProjectModel> allProjects, ConcurrentBag<SharpIdeFile> allFiles, ConcurrentBag<SharpIdeFolder> allFolders, IExpandableSharpIdeNode parent)
{ {
Name = intermediateModel.Model.Name; Name = intermediateModel.Model.Name;
Parent = parent; Parent = parent;
Files = intermediateModel.Files.Select(s => new SharpIdeFile(s.FullPath, s.Name, this, allFiles)).ToList(); Files = intermediateModel.Files.Select(s => new SharpIdeFile(s.FullPath, s.Name, this, allFiles)).ToList();
Folders = intermediateModel.Folders.Select(x => new SharpIdeSolutionFolder(x, allProjects, allFiles, this)).ToList(); Folders = intermediateModel.Folders.Select(x => new SharpIdeSolutionFolder(x, allProjects, allFiles, allFolders, this)).ToList();
Projects = intermediateModel.Projects.Select(x => new SharpIdeProjectModel(x, allProjects, allFiles, this)).ToList(); Projects = intermediateModel.Projects.Select(x => new SharpIdeProjectModel(x, allProjects, allFiles, allFolders, this)).ToList();
} }
} }
public class SharpIdeProjectModel : ISharpIdeNode, IExpandableSharpIdeNode, IChildSharpIdeNode public class SharpIdeProjectModel : ISharpIdeNode, IExpandableSharpIdeNode, IChildSharpIdeNode
@@ -88,13 +91,13 @@ public class SharpIdeProjectModel : ISharpIdeNode, IExpandableSharpIdeNode, IChi
public required Task<Project> MsBuildEvaluationProjectTask { get; set; } public required Task<Project> MsBuildEvaluationProjectTask { get; set; }
[SetsRequiredMembers] [SetsRequiredMembers]
internal SharpIdeProjectModel(IntermediateProjectModel projectModel, ConcurrentBag<SharpIdeProjectModel> allProjects, ConcurrentBag<SharpIdeFile> allFiles, IExpandableSharpIdeNode parent) internal SharpIdeProjectModel(IntermediateProjectModel projectModel, ConcurrentBag<SharpIdeProjectModel> allProjects, ConcurrentBag<SharpIdeFile> allFiles, ConcurrentBag<SharpIdeFolder> allFolders, IExpandableSharpIdeNode parent)
{ {
Parent = parent; Parent = parent;
Name = projectModel.Model.ActualDisplayName; Name = projectModel.Model.ActualDisplayName;
FilePath = projectModel.FullFilePath; FilePath = projectModel.FullFilePath;
Files = TreeMapperV2.GetFiles(projectModel.FullFilePath, this, allFiles); Files = TreeMapperV2.GetFiles(projectModel.FullFilePath, this, allFiles);
Folders = TreeMapperV2.GetSubFolders(projectModel.FullFilePath, this, allFiles); Folders = TreeMapperV2.GetSubFolders(projectModel.FullFilePath, this, allFiles, allFolders);
MsBuildEvaluationProjectTask = ProjectEvaluation.GetProject(projectModel.FullFilePath); MsBuildEvaluationProjectTask = ProjectEvaluation.GetProject(projectModel.FullFilePath);
allProjects.Add(this); allProjects.Add(this);
} }

View File

@@ -101,7 +101,7 @@ public partial class SolutionExplorerPanel : MarginContainer
} }
// Add folders under solution // Add folders under solution
foreach (var folder in SolutionModel.Folders) foreach (var folder in SolutionModel.SlnFolders)
{ {
AddSlnFolderToTree(rootItem, folder); AddSlnFolderToTree(rootItem, folder);
} }

View File

@@ -20,7 +20,7 @@
<MudTreeView T="ISharpIdeNode" Dense="true" ExpandOnClick="true" SelectedValue="@SelectedNode" SelectedValueChanged="@SelectedNodeChanged"> <MudTreeView T="ISharpIdeNode" Dense="true" ExpandOnClick="true" SelectedValue="@SelectedNode" SelectedValueChanged="@SelectedNodeChanged">
<MudTreeViewItem T="ISharpIdeNode" TextTypo="Typo.body2" Expanded="true" Icon="@Icons.Material.Filled.Folder" IconColor="Color.Primary" Value="@SolutionModel" Text="@SolutionModel.Name"> <MudTreeViewItem T="ISharpIdeNode" TextTypo="Typo.body2" Expanded="true" Icon="@Icons.Material.Filled.Folder" IconColor="Color.Primary" Value="@SolutionModel" Text="@SolutionModel.Name">
@foreach (var folder in SolutionModel.Folders) @foreach (var folder in SolutionModel.SlnFolders)
{ {
@GetSolutionFolderFragment(folder) @GetSolutionFolderFragment(folder)
} }