Display sln explorer items
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
namespace SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
|
|
||||||
|
public class SharpIdeFile
|
||||||
|
{
|
||||||
|
public required string Path { get; set; }
|
||||||
|
public required string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SharpIdeFolder
|
||||||
|
{
|
||||||
|
public required string Path { get; set; }
|
||||||
|
public required string Name { get; set; }
|
||||||
|
public required List<SharpIdeFile> Files { get; set; }
|
||||||
|
public required List<SharpIdeFolder> Folders { get; set; }
|
||||||
|
// public required int Depth { get; set; }
|
||||||
|
|
||||||
|
public bool Expanded { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
|
|
||||||
|
namespace SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
|
|
||||||
|
public static class TreeMapperV2
|
||||||
|
{
|
||||||
|
public static List<SharpIdeFolder> GetSubFolders(string csprojectPath)
|
||||||
|
{
|
||||||
|
var projectDirectory = Path.GetDirectoryName(csprojectPath)!;
|
||||||
|
var rootFolder = new SharpIdeFolder
|
||||||
|
{
|
||||||
|
Path = projectDirectory,
|
||||||
|
Name = null!,
|
||||||
|
Files = [],
|
||||||
|
Folders = []
|
||||||
|
};
|
||||||
|
var subFolders = rootFolder.GetSubFolders();
|
||||||
|
return subFolders;
|
||||||
|
}
|
||||||
|
public static List<SharpIdeFolder> GetSubFolders(this SharpIdeFolder folder)
|
||||||
|
{
|
||||||
|
var directoryInfo = new DirectoryInfo(folder.Path);
|
||||||
|
ConcurrentBag<SharpIdeFolder> subFolders = [];
|
||||||
|
|
||||||
|
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 SharpIdeFolder
|
||||||
|
{
|
||||||
|
Path = subFolderInfo.FullName,
|
||||||
|
Name = subFolderInfo.Name,
|
||||||
|
Files = GetFiles(subFolderInfo),
|
||||||
|
Folders = new SharpIdeFolder
|
||||||
|
{
|
||||||
|
Path = subFolderInfo.FullName,
|
||||||
|
Name = subFolderInfo.Name,
|
||||||
|
Files = [],
|
||||||
|
Folders = []
|
||||||
|
}.GetSubFolders()
|
||||||
|
};
|
||||||
|
|
||||||
|
subFolders.Add(subFolder);
|
||||||
|
});
|
||||||
|
|
||||||
|
return subFolders.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SharpIdeFile> GetFiles(string csprojectPath)
|
||||||
|
{
|
||||||
|
var projectDirectory = Path.GetDirectoryName(csprojectPath)!;
|
||||||
|
var directoryInfo = new DirectoryInfo(projectDirectory);
|
||||||
|
return GetFiles(directoryInfo);
|
||||||
|
}
|
||||||
|
public static List<SharpIdeFile> GetFiles(DirectoryInfo directoryInfo)
|
||||||
|
{
|
||||||
|
List<FileInfo> fileInfos;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fileInfos = directoryInfo.EnumerateFiles().ToList();
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileInfos.Select(f => new SharpIdeFile
|
||||||
|
{
|
||||||
|
Path = f.FullName,
|
||||||
|
Name = f.Name
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,4 +21,5 @@ public class IntermediateProjectModel
|
|||||||
{
|
{
|
||||||
public required SolutionProjectModel Model { get; set; }
|
public required SolutionProjectModel Model { get; set; }
|
||||||
public required string FullFilePath { get; set; }
|
public required string FullFilePath { get; set; }
|
||||||
|
public required Guid Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,4 +17,6 @@ public class SharpIdeProjectModel
|
|||||||
{
|
{
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public required string FilePath { get; set; }
|
public required string FilePath { get; set; }
|
||||||
|
public required List<SharpIdeFolder> Folders { get; set; }
|
||||||
|
public required List<SharpIdeFile> Files { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,14 @@ public static class VsPersistenceMapper
|
|||||||
|
|
||||||
return solutionModel;
|
return solutionModel;
|
||||||
}
|
}
|
||||||
private static SharpIdeProjectModel GetSharpIdeProjectModel(IntermediateProjectModel projectModel) => new SharpIdeProjectModel()
|
private static SharpIdeProjectModel GetSharpIdeProjectModel(IntermediateProjectModel projectModel) => new SharpIdeProjectModel
|
||||||
{
|
{
|
||||||
Name = projectModel.Model.DisplayName!,
|
Name = projectModel.Model.ActualDisplayName,
|
||||||
FilePath = projectModel.Model.FilePath,
|
FilePath = projectModel.Model.FilePath,
|
||||||
};
|
Files = TreeMapperV2.GetFiles(projectModel.FullFilePath),
|
||||||
|
Folders = TreeMapperV2.GetSubFolders(projectModel.FullFilePath)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
private static SharpIdeSolutionFolder GetSharpIdeSolutionFolder(IntermediateSlnFolderModel folderModel) => new SharpIdeSolutionFolder()
|
private static SharpIdeSolutionFolder GetSharpIdeSolutionFolder(IntermediateSlnFolderModel folderModel) => new SharpIdeSolutionFolder()
|
||||||
{
|
{
|
||||||
@@ -49,7 +52,7 @@ public static class VsPersistenceMapper
|
|||||||
|
|
||||||
var rootFolders = vsSolution.SolutionFolders
|
var rootFolders = vsSolution.SolutionFolders
|
||||||
.Where(f => f.Parent is null)
|
.Where(f => f.Parent is null)
|
||||||
.Select(f => BuildFolderTree(f, vsSolution.SolutionFolders, vsSolution.SolutionProjects))
|
.Select(f => BuildFolderTree(f, solutionFilePath, vsSolution.SolutionFolders, vsSolution.SolutionProjects))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var solutionModel = new IntermediateSolutionModel
|
var solutionModel = new IntermediateSolutionModel
|
||||||
@@ -59,19 +62,20 @@ public static class VsPersistenceMapper
|
|||||||
Projects = vsSolution.SolutionProjects.Where(p => p.Parent is null).Select(s => new IntermediateProjectModel
|
Projects = vsSolution.SolutionProjects.Where(p => p.Parent is null).Select(s => new IntermediateProjectModel
|
||||||
{
|
{
|
||||||
Model = s,
|
Model = s,
|
||||||
FullFilePath = Path.GetFullPath(s.FilePath)
|
Id = s.Id,
|
||||||
|
FullFilePath = new DirectoryInfo(Path.Join(Path.GetDirectoryName(solutionFilePath), s.FilePath)).FullName
|
||||||
}).ToList(),
|
}).ToList(),
|
||||||
SolutionFolders = rootFolders
|
SolutionFolders = rootFolders
|
||||||
};
|
};
|
||||||
return solutionModel;
|
return solutionModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IntermediateSlnFolderModel BuildFolderTree(SolutionFolderModel folder,
|
private static IntermediateSlnFolderModel BuildFolderTree(SolutionFolderModel folder, string solutionFilePath,
|
||||||
IReadOnlyList<SolutionFolderModel> allSolutionFolders, IReadOnlyList<SolutionProjectModel> allSolutionProjects)
|
IReadOnlyList<SolutionFolderModel> allSolutionFolders, IReadOnlyList<SolutionProjectModel> allSolutionProjects)
|
||||||
{
|
{
|
||||||
var childFolders = allSolutionFolders
|
var childFolders = allSolutionFolders
|
||||||
.Where(f => f.Parent == folder)
|
.Where(f => f.Parent == folder)
|
||||||
.Select(f => BuildFolderTree(f, allSolutionFolders, allSolutionProjects))
|
.Select(f => BuildFolderTree(f, solutionFilePath, allSolutionFolders, allSolutionProjects))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var projectsInFolder = allSolutionProjects
|
var projectsInFolder = allSolutionProjects
|
||||||
@@ -79,7 +83,8 @@ public static class VsPersistenceMapper
|
|||||||
.Select(s => new IntermediateProjectModel
|
.Select(s => new IntermediateProjectModel
|
||||||
{
|
{
|
||||||
Model = s,
|
Model = s,
|
||||||
FullFilePath = Path.GetFullPath(s.FilePath)
|
Id = s.Id,
|
||||||
|
FullFilePath = new DirectoryInfo(Path.Join(Path.GetDirectoryName(solutionFilePath), s.FilePath)).FullName
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,23 @@
|
|||||||
@using Ardalis.GuardClauses
|
@using SharpIDE.Application.Features.SolutionDiscovery
|
||||||
@using Microsoft.Build.Construction
|
|
||||||
@using SharpIDE.Application.Features.SolutionDiscovery
|
|
||||||
@using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence
|
@using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence
|
||||||
|
|
||||||
@if (_solutionFile is null)
|
@if (SolutionModel is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
<MudTreeView T="SharpIdeSolutionModel" Dense="true">
|
||||||
<MudTreeView T="ProjectInSolution" Dense="true" >
|
<MudTreeViewItem TextTypo="Typo.body2" Expanded="true" Icon="@Icons.Material.Filled.Folder" IconColor="Color.Primary" Value="@SolutionModel" Text="@SolutionModel.Name">
|
||||||
@foreach(var project in _rootNodes)
|
<MudTreeView Dense="true">
|
||||||
{
|
@foreach (var folder in SolutionModel.Folders)
|
||||||
@GetProjectFragment(project)
|
{
|
||||||
}
|
@GetSolutionFolderFragment(folder)
|
||||||
|
}
|
||||||
|
@foreach(var project in SolutionModel.Projects)
|
||||||
|
{
|
||||||
|
@GetProjectFragment(project)
|
||||||
|
}
|
||||||
|
</MudTreeView>
|
||||||
|
</MudTreeViewItem>
|
||||||
</MudTreeView>
|
</MudTreeView>
|
||||||
|
|
||||||
|
|
||||||
@@ -23,71 +28,56 @@
|
|||||||
[Parameter, EditorRequired]
|
[Parameter, EditorRequired]
|
||||||
public SharpIdeSolutionModel SolutionModel { get; set; } = null!;
|
public SharpIdeSolutionModel SolutionModel { get; set; } = null!;
|
||||||
|
|
||||||
private SolutionFile _solutionFile = null!;
|
private RenderFragment GetSolutionFolderFragment(SharpIdeSolutionFolder slnFolder) =>
|
||||||
private List<ProjectInSolution> _rootNodes = [];
|
|
||||||
private Dictionary<string, Folder?> _folders = new();
|
|
||||||
|
|
||||||
private RenderFragment GetProjectFragment(ProjectInSolution project) =>
|
|
||||||
@<text>
|
@<text>
|
||||||
<MudTreeViewItem TextTypo="Typo.body2" Icon="@Icons.Material.Filled.Folder" IconColor="Color.Primary" Value="project" Text="@project.ProjectName">
|
<MudTreeViewItem TextTypo="Typo.body2" Icon="@Icons.Material.Filled.Folder" IconColor="Color.Primary" Value="@slnFolder" Text="@slnFolder.Name">
|
||||||
@foreach(var child in _solutionFile.ProjectsByGuid.Values.Where(s => s.ParentProjectGuid == project.ProjectGuid).OrderBy(s => s.ProjectName))
|
@foreach(var childFolder in slnFolder.Folders)
|
||||||
{
|
{
|
||||||
@GetProjectFragment(child)
|
@GetSolutionFolderFragment(childFolder)
|
||||||
}
|
}
|
||||||
@if (_folders.GetValueOrDefault(project.ProjectGuid, null) is {} value)
|
@foreach(var childProject in slnFolder.Projects)
|
||||||
{
|
{
|
||||||
@GetFolderFragment(value)
|
@GetProjectFragment(childProject)
|
||||||
}
|
}
|
||||||
</MudTreeViewItem>
|
</MudTreeViewItem>
|
||||||
</text>;
|
</text>;
|
||||||
|
|
||||||
private RenderFragment GetFolderFragment(Folder folder) =>
|
private RenderFragment GetProjectFragment(SharpIdeProjectModel project) =>
|
||||||
@<text>
|
@<text>
|
||||||
@foreach (var subFolder in folder.Folders)
|
<MudTreeViewItem TextTypo="Typo.body2" Icon="@Icons.Material.Filled.Folder" IconColor="Color.Primary" Text="@project.Name" Value="project">
|
||||||
{
|
@foreach (var folder in project.Folders)
|
||||||
<MudTreeViewItem TextTypo="Typo.body2" @bind-Expanded="subFolder.Expanded" T="ProjectInSolution" Text="@subFolder.Name">
|
{
|
||||||
@if (subFolder.Expanded)
|
<MudTreeViewItem TextTypo="Typo.body2" Icon="@Icons.Material.Filled.Folder" IconColor="Color.Default" @bind-Expanded="folder.Expanded" Text="@folder.Name" Value="@folder">
|
||||||
{
|
@GetFolderFragment(folder)
|
||||||
@GetFolderFragment(subFolder)
|
</MudTreeViewItem>
|
||||||
}
|
}
|
||||||
</MudTreeViewItem>
|
@foreach(var file in project.Files)
|
||||||
}
|
{
|
||||||
@foreach (var file in folder.Files)
|
@GetFileFragment(file)
|
||||||
{
|
}
|
||||||
<MudTreeViewItem TextTypo="Typo.body2" T="ProjectInSolution" Text="@file.Name" />
|
</MudTreeViewItem>
|
||||||
}
|
</text>;
|
||||||
</text>;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
private RenderFragment GetFolderFragment(SharpIdeFolder folder) =>
|
||||||
{
|
@<text>
|
||||||
Guard.Against.NullOrWhiteSpace(SolutionFilePath);
|
@foreach (var subFolder in folder.Folders)
|
||||||
await Task.Run(() => LoadSolution(SolutionFilePath));
|
{
|
||||||
}
|
<MudTreeViewItem TextTypo="Typo.body2" Icon="@Icons.Material.Filled.Folder" IconColor="Color.Default" @bind-Expanded="subFolder.Expanded" Text="@subFolder.Name" Value="@subFolder">
|
||||||
|
@if (subFolder.Expanded)
|
||||||
|
{
|
||||||
|
@GetFolderFragment(subFolder)
|
||||||
|
}
|
||||||
|
</MudTreeViewItem>
|
||||||
|
}
|
||||||
|
@foreach (var file in folder.Files)
|
||||||
|
{
|
||||||
|
@GetFileFragment(file)
|
||||||
|
}
|
||||||
|
</text>;
|
||||||
|
|
||||||
private void LoadSolution(string solutionPath)
|
private RenderFragment GetFileFragment(SharpIdeFile file) =>
|
||||||
{
|
@<text>
|
||||||
var solutionFile = GetNodesInSolution.ParseSolutionFileFromPath(solutionPath);
|
<MudTreeViewItem T="SharpIdeFile" TextTypo="Typo.body2" Text="@file.Name"/>
|
||||||
ArgumentNullException.ThrowIfNull(solutionFile);
|
</text>;
|
||||||
_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!;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
@* @Body *@
|
@* @Body *@
|
||||||
@if (_solutionFilePath is not null)
|
@if (_solutionFilePath is not null)
|
||||||
{
|
{
|
||||||
<CodeViewer FilePath="C:\Users\matth\Documents\Git\SharpIDE.Photino\src\SharpIDE.Photino\Program.cs" />
|
<CodeViewer FilePath="C:\Users\Matthew\Documents\Git\SharpIDE.Photino\src\SharpIDE.Photino\Program.cs" />
|
||||||
}
|
}
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
</MudMainContent>
|
</MudMainContent>
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
var solutionFilePath = (string)result.Data!;
|
var solutionFilePath = (string)result.Data!;
|
||||||
_solutionFilePath = solutionFilePath;
|
_solutionFilePath = solutionFilePath;
|
||||||
|
|
||||||
await BuildService.BuildSolutionAsync(_solutionFilePath);
|
//await BuildService.BuildSolutionAsync(_solutionFilePath);
|
||||||
var solutionModel = await VsPersistenceMapper.GetSolutionModel(_solutionFilePath);
|
var solutionModel = await VsPersistenceMapper.GetSolutionModel(_solutionFilePath);
|
||||||
_solutionModel = solutionModel;
|
_solutionModel = solutionModel;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user