This commit is contained in:
Matt Parker [SSW]
2025-01-10 20:07:13 +10:00
parent e53bde1776
commit 3178cea5a3
9 changed files with 171 additions and 108 deletions

View File

@@ -1,14 +1,22 @@
namespace SharpIDE.Application.Features.SolutionDiscovery;
using System.Text.Json.Serialization;
namespace SharpIDE.Application.Features.SolutionDiscovery;
public class Folder
{
public required string Name { get; set; }
public required string FullName { get; set; }
public required Folder? ParentFolder { get; set; }
public required List<MyFile> Files { get; set; } = [];
public required string Path { get; set; }
public string Name { get; set; } = null!;
public List<Folder> Folders { get; set; } = [];
public List<TreeMapFile> Files { get; set; } = [];
public bool IsPseudoFolder { get; set; }
public int Depth { get; set; }
[JsonIgnore]
public bool Expanded { get; set; }
}
public class MyFile
public class TreeMapFile
{
public required string Path { get; set; }
public required string Name { get; set; }
}

View File

@@ -44,35 +44,7 @@ public static class GetNodesInSolution
var rootDirectoryOfProject = new DirectoryInfo(Path.GetDirectoryName(projectPath)!);
var grouped = files.GroupBy(s => s.Directory!.FullName);
var folders = grouped.Select(s => new Folder
{
Name = Path.GetFileName(s.Key),
FullName = s.Key,
ParentFolder = null,
Files = s.Select(f => new MyFile
{
Name = f.Name
}).ToList()
}).ToList();
foreach (var folder in folders)
{
var directoryInfo = new DirectoryInfo(folder.FullName);
if (directoryInfo.FullName == rootDirectoryOfProject.FullName) continue;
var parent = directoryInfo.Parent;
try
{
var parentFolder = folders.SingleOrDefault(f => f.FullName == parent!.FullName);
folder.ParentFolder = parentFolder;
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
return folders;
throw new NotImplementedException();
}
}

View File

@@ -0,0 +1,69 @@
using System.Collections.Concurrent;
namespace SharpIDE.Application.Features.SolutionDiscovery;
public static class TreeMapper
{
public static List<Folder> GetSubFolders(this Folder folder)
{
var directoryInfo = new DirectoryInfo(folder.Path);
ConcurrentBag<Folder> subFolders = [];
var files = GetFiles(directoryInfo);
if (files.Count is not 0)
{
var pseudoFolder = new Folder
{
Path = folder.Path,
Name = "<Files>",
IsPseudoFolder = true,
Files = files,
Depth = folder.Depth + 1
};
subFolders.Add(pseudoFolder);
}
List<DirectoryInfo> subFolderInfos;
try
{
subFolderInfos = directoryInfo.EnumerateDirectories("*", new EnumerationOptions { IgnoreInaccessible = false, AttributesToSkip = FileAttributes.ReparsePoint}).ToList();
}
catch (UnauthorizedAccessException)
{
return subFolders.ToList();
}
Parallel.ForEach(subFolderInfos, subFolderInfo =>
{
var subFolder = new Folder
{
Path = subFolderInfo.FullName,
Name = subFolderInfo.Name,
Depth = folder.Depth + 1
};
subFolder.Folders = subFolder.GetSubFolders();
subFolders.Add(subFolder);
});
return subFolders.ToList();
}
public static List<TreeMapFile> GetFiles(DirectoryInfo directoryInfo)
{
List<FileInfo> fileInfos;
try
{
fileInfos = directoryInfo.EnumerateFiles().ToList();
}
catch (UnauthorizedAccessException)
{
return [];
}
var files = fileInfos.Select(s => new TreeMapFile
{
Path = s.FullName,
Name = s.Name
}).ToList();
return files;
}
}

View File

@@ -0,0 +1,80 @@
@using Microsoft.Build.Construction
@using SharpIDE.Application.Features.SolutionDiscovery
@if (_solutionFile is null)
{
return;
}
<MudTreeView T="ProjectInSolution" Dense="true">
@foreach(var project in _rootNodes)
{
@GetProjectFragment(project)
}
</MudTreeView>
@code {
private SolutionFile _solutionFile = null!;
private List<ProjectInSolution> _rootNodes = [];
private Dictionary<string, Folder> _folders = new();
private RenderFragment GetProjectFragment(ProjectInSolution project) =>
@<text>
<MudTreeViewItem Value="project" Text="@project.ProjectName">
@foreach(var child in _solutionFile.ProjectsByGuid.Values.Where(s => s.ParentProjectGuid == project.ProjectGuid).OrderBy(s => s.ProjectName))
{
@GetProjectFragment(child)
}
@if (_folders.GetValueOrDefault(project.ProjectGuid, null) is {} value)
{
@GetFolderFragment(value)
}
</MudTreeViewItem>
</text>;
private RenderFragment GetFolderFragment(Folder folder) =>
@<text>
@foreach (var subFolder in folder.Folders)
{
<MudTreeViewItem @bind-Expanded="subFolder.Expanded" T="ProjectInSolution" Text="@subFolder.Name">
@if (subFolder.Expanded)
{
@GetFolderFragment(subFolder)
}
</MudTreeViewItem>
}
@foreach (var file in folder.Files)
{
<MudTreeViewItem T="ProjectInSolution" Text="@file.Name" />
}
</text>;
protected override async Task OnInitializedAsync()
{
var solutionFile = GetNodesInSolution.ParseSolutionFileFromPath("D:/matth/Documents/Git/amazon/ClientPortal.sln");
ArgumentNullException.ThrowIfNull(solutionFile);
_solutionFile = solutionFile;
var rootNodes = solutionFile.ProjectsByGuid.Values.Where(p => p.ParentProjectGuid == null).OrderBy(s => s.ProjectName).ToList();
_rootNodes = rootNodes;
var folders2 = _solutionFile.ProjectsByGuid.Values
.Where(s => s.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
//.Take(2)
.Select(s =>
{
var rootFolder = new Folder
{
Name = Path.GetFileNameWithoutExtension(s.AbsolutePath),
Path = Path.GetDirectoryName(s.AbsolutePath)!,
IsPseudoFolder = false
};
rootFolder.Folders = rootFolder.GetSubFolders();
return (s, rootFolder);
})
.ToDictionary(s => s.s.ProjectGuid, s => s.Item2);
_folders = folders2;
}
}

View File

@@ -9,13 +9,9 @@
<MudAppBar Dense="true">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@((e) => DrawerToggle())" />
</MudAppBar>
<MudDrawer @bind-Open="@_drawerOpen">
<MudDrawerHeader>
<MudStack Row="false" Justify="Justify.Center">
<MudText Typo="Typo.h5">SharpIDE.Photino</MudText>
</MudStack>
</MudDrawerHeader>
<NavMenu/>
<MudDrawer @bind-Open="@_drawerOpen" ClipMode="DrawerClipMode.Always">
<SolutionExplorer />
@* <NavMenu/> *@
</MudDrawer>
<MudMainContent>
<MudContainer Class="px-8 py-6">

View File

@@ -1,3 +1,3 @@
<MudNavMenu>
<MudNavLink Href="/" Icon="@Icons.Material.Filled.Home" Match="NavLinkMatch.All">Home</MudNavLink>
<MudNavLink Href="/" Icon="@Icons.Material.Filled.Home" Match="NavLinkMatch.All">Solution Explorer</MudNavLink>
</MudNavMenu>

View File

@@ -1,71 +1,8 @@
@page "/"
@using Microsoft.Build.Construction
@using Microsoft.Build.Evaluation
@using Microsoft.Build.Execution
@using Microsoft.Build.Globbing
@using Microsoft.Build.Globbing.Extensions
@using SharpIDE.Application.Features.SolutionDiscovery
<MudText>Welcome to a new Photino Blazor app!</MudText>
@if (_solutionFile is null)
@code
{
return;
}
<MudTreeView T="ProjectInSolution" Dense="true">
@foreach(var project in _rootNodes)
{
@GetProjectFragment(project)
}
</MudTreeView>
@code {
private SolutionFile _solutionFile = null!;
private List<ProjectInSolution> _rootNodes = [];
private Dictionary<string, List<Folder>> _folders = new();
private RenderFragment GetProjectFragment(ProjectInSolution project) =>
@<text>
<MudTreeViewItem Value="project" Text="@project.ProjectName">
@foreach(var child in _solutionFile.ProjectsByGuid.Values.Where(s => s.ParentProjectGuid == project.ProjectGuid).OrderBy(s => s.ProjectName))
{
@GetProjectFragment(child)
}
@GetFolderFragment(_folders.GetValueOrDefault(project.ProjectGuid, []))
</MudTreeViewItem>
</text>;
private RenderFragment GetFolderFragment(List<Folder> folders) =>
@<text>
@foreach (var folder in folders.Where(s => s.ParentFolder is null))
{
<MudTreeViewItem T="ProjectInSolution" Text="@folder.Name">
@GetFolderFragment(folders.Where(s => s.ParentFolder == folder).ToList())
@foreach(var file in folder.Files)
{
<MudTreeViewItem T="ProjectInSolution" Text="@file.Name" />
}
</MudTreeViewItem>
}
</text>;
protected override async Task OnInitializedAsync()
{
var solutionFile = GetNodesInSolution.ParseSolutionFileFromPath("D:/matth/Documents/Git/amazon/ClientPortal.sln");
ArgumentNullException.ThrowIfNull(solutionFile);
_solutionFile = solutionFile;
var rootNodes = solutionFile.ProjectsByGuid.Values.Where(p => p.ParentProjectGuid == null).OrderBy(s => s.ProjectName).ToList();
_rootNodes = rootNodes;
var folders2 = _solutionFile.ProjectsByGuid.Values
.Where(s => s.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
.Take(2)
.Select(s => (s, GetNodesInSolution.GetFoldersInProject(s.AbsolutePath)))
.ToDictionary(s => s.s.ProjectGuid, s => s.Item2);
_folders = folders2;
}
}

View File

@@ -19,7 +19,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebView" Version="9.0.0" />
<PackageReference Include="MudBlazor" Version="8.0.0-preview.5" />
<PackageReference Include="MudBlazor" Version="8.0.0-rc.2" />
<PackageReference Include="Photino.Blazor" Version="3.2.0" />
</ItemGroup>

View File

@@ -9,3 +9,4 @@
@using Microsoft.Extensions.Logging
@using MudBlazor
@using SharpIDE.Photino.Layout
@using SharpIDE.Photino.Components