Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 141 additions & 12 deletions src/Components/SolutionExplorer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,64 @@ module SolutionExplorer =

entry.Children |> Seq.rev |> Seq.map (toModel projPath) |> Seq.toList

// File extension to item type mapping
let getItemTypeForFile (filePath: string) =
let ext = node.path.extname(filePath).ToLowerInvariant()

match ext with
| ".fs"
| ".fsi" -> "Compile"
| ".fsx" -> "Compile"
| ".fsl" -> "FsLex"
| ".fsy" -> "FsYacc"
| ".txt"
| ".md"
| ".json"
| ".xml"
| ".config" -> "Content"
| ".resx" -> "EmbeddedResource"
| ".dll"
| ".exe" -> "Reference"
| _ -> "Content" // Default fallback

let private getProjectModel (proj: Project) =
let projects = Project.getLoaded () |> Seq.toArray

let files =
proj.Items
|> Seq.filter (fun p -> p.Name = "Compile")
|> Seq.map (fun p -> p.VirtualPath, p.FilePath)
|> Seq.toList
|> buildTree proj.Project

// Get project files from FSAC
let projectFiles =
proj.Items |> Seq.map (fun p -> p.VirtualPath, p.FilePath) |> Seq.toList

// Add additional folders that aren't in the project file
let projectDir = node.path.dirname proj.Project

let additionalFolders =
try
let dirContents = node.fs.readdirSync (U2.Case1 projectDir)

dirContents
|> Seq.filter (fun item ->
let fullPath = node.path.join (projectDir, item)
let stats = node.fs.statSync (U2.Case1 fullPath)
let isDir = stats.isDirectory ()

let isTargetFolder =
(item = ".deps" || item = "bin" || item = "obj" || item = "packages")

isDir && isTargetFolder)
|> Seq.map (fun folder ->
let fullPath = node.path.join (projectDir, folder)
(folder, fullPath))
|> Seq.toList
with ex ->
[]

// Combine project files with additional folders
let allItems =
projectFiles
@ (additionalFolders |> List.map (fun (name, path) -> (name, path)))

let files = buildTree proj.Project allItems

let packageRefs =
proj.PackageReferences
Expand Down Expand Up @@ -245,13 +294,93 @@ module SolutionExplorer =

match ws with
| WorkspacePeekFound.Solution sln ->
// Get solution items from the solution file
let solutionItems = sln.Items |> Array.map getItem |> List.ofArray

// Add additional folders that aren't in the solution file
let solutionDir = node.path.dirname sln.Path

let additionalSolutionFolders =
try
let dirContents = node.fs.readdirSync (U2.Case1 solutionDir)

dirContents
|> Seq.filter (fun item ->
let fullPath = node.path.join (solutionDir, item)
let stats = node.fs.statSync (U2.Case1 fullPath)
let isDir = stats.isDirectory ()

let isTargetFolder =
(item = ".deps"
|| item = "bin"
|| item = "obj"
|| item = "packages"
|| item = "docs"
|| item = "scripts"
|| item = "tools")


isDir && isTargetFolder)
|> Seq.map (fun folder ->
let fullPath = node.path.join (solutionDir, folder)

// Recursively scan the contents of this folder
let rec scanFolderContents (currentPath: string) (currentName: string) (depth: int) =
try
let contents = node.fs.readdirSync (U2.Case1 currentPath)

contents
|> Seq.filter (fun item ->
// Filter out unwanted items at solution level
let isUnwanted =
item.StartsWith(".") && item <> ".deps"
|| // Hide hidden files except .deps
item = "node_modules"
|| // Hide node_modules
item = ".git"
|| // Hide git folder
item = ".vs"
|| // Hide Visual Studio folder
item = "packages" && depth > 0 // Hide nested packages folders

not isUnwanted)
|> Seq.map (fun item ->
let itemPath = node.path.join (currentPath, item)
let stats = node.fs.statSync (U2.Case1 itemPath)

if stats.isDirectory () then
// Recursively scan subdirectories (limit depth to avoid infinite recursion)
if depth < 6 then
let subContents = scanFolderContents itemPath item (depth + 1)
Model.Folder(ref None, item, itemPath, subContents, "")
else
// For very deep directories, just show as empty folder
Model.Folder(ref None, item, itemPath, [], "")
else
// Use the same file type mapping as project level
let ext = node.path.extname(item).ToLowerInvariant()
let itemType = getItemTypeForFile item

// For files, create a file representation
Model.File(ref None, itemPath, item, None, ""))
|> Seq.toList
with ex ->
[]

let folderContents = scanFolderContents fullPath folder 0


// Create a WorkspaceFolder with the scanned contents
Model.WorkspaceFolder(ref None, folder, folderContents))
|> Seq.toList
with ex ->
[]

// Combine solution items with additional folders
let allSolutionItems = solutionItems @ additionalSolutionFolders

let s =
Solution(
ref None,
sln.Path,
(node.path.basename sln.Path),
(sln.Items |> Array.map getItem |> List.ofArray)
)
Solution(ref None, sln.Path, (node.path.basename sln.Path), allSolutionItems)

let result = Workspace [ s ]
setParentRef s result
Expand Down
Loading