Skip to content

Commit eed1042

Browse files
committed
updates to file type filtering (#2103)
1 parent 9475ff3 commit eed1042

File tree

1 file changed

+140
-90
lines changed

1 file changed

+140
-90
lines changed

src/Components/SolutionExplorer.fs

Lines changed: 140 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ module SolutionExplorer =
4040
path: string *
4141
name: string *
4242
virtualPath: string option *
43-
projectPath: string *
44-
itemType: string option *
45-
metadata: Map<string, string> option
43+
projectPath: string
4644
| PackageReference of parent: Model option ref * path: string * name: string * projectPath: string
4745
| ProjectReference of parent: Model option ref * path: string * name: string * projectPath: string
4846

@@ -99,7 +97,7 @@ module SolutionExplorer =
9997
| ProjectLanguageNotSupported(parent, _, _) -> parent
10098
| Project(parent, _, _, _, _, _, _, _) -> parent
10199
| Folder(parent, _, _, _, _) -> parent
102-
| File(parent, _, _, _, _, _, _) -> parent
100+
| File(parent, _, _, _, _) -> parent
103101
| PackageReference(parent, _, _, _) -> parent
104102
| ProjectReference(parent, _, _, _) -> parent
105103

@@ -133,32 +131,7 @@ module SolutionExplorer =
133131
setParentRefs childs result
134132
result
135133
else
136-
File(ref None, entry.FilePath, entry.Key, Some entry.VirtualPath, projPath, None, None)
137-
138-
let rec toModelWithMetadata
139-
(projPath: string)
140-
(files: (string * string * string option * Map<string, string> option) list)
141-
(entry: NodeEntry)
142-
=
143-
if entry.Children.Length > 0 then
144-
let childs =
145-
entry.Children |> Seq.map (toModelWithMetadata projPath files) |> Seq.toList
146-
147-
let result = Folder(ref None, entry.Key, entry.FilePath, childs, projPath)
148-
setParentRefs childs result
149-
result
150-
else
151-
let fileMetadata =
152-
files
153-
|> List.tryFind (fun (_, path, _, _) -> path = entry.FilePath)
154-
|> Option.map (fun (_, _, itemType, metadata) -> (itemType, metadata))
155-
156-
let (itemType, metadata) =
157-
match fileMetadata with
158-
| Some(it, md) -> (it, md)
159-
| None -> (None, None)
160-
161-
File(ref None, entry.FilePath, entry.Key, Some entry.VirtualPath, projPath, itemType, metadata)
134+
File(ref None, entry.FilePath, entry.Key, Some entry.VirtualPath, projPath)
162135

163136
let buildTree projPath (files: (string * string) list) =
164137
let projDir = dirName projPath
@@ -173,37 +146,6 @@ module SolutionExplorer =
173146

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

176-
let buildTreeWithMetadata projPath (files: (string * string * string option * Map<string, string> option) list) =
177-
let projDir = dirName projPath
178-
179-
let entry =
180-
{ Key = ""
181-
FilePath = projDir
182-
VirtualPath = ""
183-
Children = [] }
184-
185-
files
186-
|> List.iter (fun (virtualPath, path, _, _) -> add' entry virtualPath path)
187-
188-
entry.Children
189-
|> Seq.rev
190-
|> Seq.map (toModelWithMetadata projPath files)
191-
|> Seq.toList
192-
193-
let ignoredItemTypes =
194-
Set.ofList
195-
[ "AssemblyMetadata"
196-
"BaseApplicationManifest"
197-
"CodeAnalysisImport"
198-
"COMReference"
199-
"COMFileReference"
200-
"Import"
201-
"InternalsVisibleTo"
202-
"NativeReference"
203-
"TrimmerRootAssembly"
204-
"Using"
205-
"Protobuf" ]
206-
207149
// File extension to item type mapping
208150
let getItemTypeForFile (filePath: string) =
209151
let ext = node.path.extname(filePath).ToLowerInvariant()
@@ -220,20 +162,48 @@ module SolutionExplorer =
220162
| ".xml"
221163
| ".config" -> "Content"
222164
| ".resx" -> "EmbeddedResource"
165+
| ".dll"
166+
| ".exe" -> "Reference"
223167
| _ -> "Content" // Default fallback
224168

225-
let shouldShowItem (item: ProjectResponseItem) =
226-
not (ignoredItemTypes.Contains(item.Name))
227-
228169
let private getProjectModel (proj: Project) =
229170
let projects = Project.getLoaded () |> Seq.toArray
230171

231-
let files =
232-
proj.Items
233-
|> Seq.filter shouldShowItem
234-
|> Seq.map (fun p -> p.VirtualPath, p.FilePath, Some p.Name, Some p.Metadata)
235-
|> Seq.toList
236-
|> buildTreeWithMetadata proj.Project
172+
173+
// Get project files from FSAC
174+
let projectFiles =
175+
proj.Items |> Seq.map (fun p -> p.VirtualPath, p.FilePath) |> Seq.toList
176+
177+
// Add additional folders that aren't in the project file
178+
let projectDir = node.path.dirname proj.Project
179+
180+
let additionalFolders =
181+
try
182+
let dirContents = node.fs.readdirSync (U2.Case1 projectDir)
183+
184+
dirContents
185+
|> Seq.filter (fun item ->
186+
let fullPath = node.path.join (projectDir, item)
187+
let stats = node.fs.statSync (U2.Case1 fullPath)
188+
let isDir = stats.isDirectory ()
189+
190+
let isTargetFolder =
191+
(item = ".deps" || item = "bin" || item = "obj" || item = "packages")
192+
193+
isDir && isTargetFolder)
194+
|> Seq.map (fun folder ->
195+
let fullPath = node.path.join (projectDir, folder)
196+
(folder, fullPath))
197+
|> Seq.toList
198+
with ex ->
199+
[]
200+
201+
// Combine project files with additional folders
202+
let allItems =
203+
projectFiles
204+
@ (additionalFolders |> List.map (fun (name, path) -> (name, path)))
205+
206+
let files = buildTree proj.Project allItems
237207

238208
let packageRefs =
239209
proj.PackageReferences
@@ -310,7 +280,7 @@ module SolutionExplorer =
310280
| WorkspacePeekFoundSolutionItemKind.Folder folder ->
311281
let files =
312282
folder.Files
313-
|> Array.map (fun f -> Model.File(ref None, f, node.path.basename (f), None, "", None, None))
283+
|> Array.map (fun f -> Model.File(ref None, f, node.path.basename (f), None, ""))
314284

315285
let items = folder.Items |> Array.map getItem
316286

@@ -324,13 +294,93 @@ module SolutionExplorer =
324294

325295
match ws with
326296
| WorkspacePeekFound.Solution sln ->
297+
// Get solution items from the solution file
298+
let solutionItems = sln.Items |> Array.map getItem |> List.ofArray
299+
300+
// Add additional folders that aren't in the solution file
301+
let solutionDir = node.path.dirname sln.Path
302+
303+
let additionalSolutionFolders =
304+
try
305+
let dirContents = node.fs.readdirSync (U2.Case1 solutionDir)
306+
307+
dirContents
308+
|> Seq.filter (fun item ->
309+
let fullPath = node.path.join (solutionDir, item)
310+
let stats = node.fs.statSync (U2.Case1 fullPath)
311+
let isDir = stats.isDirectory ()
312+
313+
let isTargetFolder =
314+
(item = ".deps"
315+
|| item = "bin"
316+
|| item = "obj"
317+
|| item = "packages"
318+
|| item = "docs"
319+
|| item = "scripts"
320+
|| item = "tools")
321+
322+
323+
isDir && isTargetFolder)
324+
|> Seq.map (fun folder ->
325+
let fullPath = node.path.join (solutionDir, folder)
326+
327+
// Recursively scan the contents of this folder
328+
let rec scanFolderContents (currentPath: string) (currentName: string) (depth: int) =
329+
try
330+
let contents = node.fs.readdirSync (U2.Case1 currentPath)
331+
332+
contents
333+
|> Seq.filter (fun item ->
334+
// Filter out unwanted items at solution level
335+
let isUnwanted =
336+
item.StartsWith(".") && item <> ".deps"
337+
|| // Hide hidden files except .deps
338+
item = "node_modules"
339+
|| // Hide node_modules
340+
item = ".git"
341+
|| // Hide git folder
342+
item = ".vs"
343+
|| // Hide Visual Studio folder
344+
item = "packages" && depth > 0 // Hide nested packages folders
345+
346+
not isUnwanted)
347+
|> Seq.map (fun item ->
348+
let itemPath = node.path.join (currentPath, item)
349+
let stats = node.fs.statSync (U2.Case1 itemPath)
350+
351+
if stats.isDirectory () then
352+
// Recursively scan subdirectories (limit depth to avoid infinite recursion)
353+
if depth < 6 then
354+
let subContents = scanFolderContents itemPath item (depth + 1)
355+
Model.Folder(ref None, item, itemPath, subContents, "")
356+
else
357+
// For very deep directories, just show as empty folder
358+
Model.Folder(ref None, item, itemPath, [], "")
359+
else
360+
// Use the same file type mapping as project level
361+
let ext = node.path.extname(item).ToLowerInvariant()
362+
let itemType = getItemTypeForFile item
363+
364+
// For files, create a file representation
365+
Model.File(ref None, itemPath, item, None, ""))
366+
|> Seq.toList
367+
with ex ->
368+
[]
369+
370+
let folderContents = scanFolderContents fullPath folder 0
371+
372+
373+
// Create a WorkspaceFolder with the scanned contents
374+
Model.WorkspaceFolder(ref None, folder, folderContents))
375+
|> Seq.toList
376+
with ex ->
377+
[]
378+
379+
// Combine solution items with additional folders
380+
let allSolutionItems = solutionItems @ additionalSolutionFolders
381+
327382
let s =
328-
Solution(
329-
ref None,
330-
sln.Path,
331-
(node.path.basename sln.Path),
332-
(sln.Items |> Array.map getItem |> List.ofArray)
333-
)
383+
Solution(ref None, sln.Path, (node.path.basename sln.Path), allSolutionItems)
334384

335385
let result = Workspace [ s ]
336386
setParentRef s result
@@ -382,7 +432,7 @@ module SolutionExplorer =
382432
| PackageReferenceList _ -> "Package References"
383433
| ProjectReferencesList(_, refs, _) -> "Project References"
384434
| Folder(_, n, _, _, _) -> n
385-
| File(_, _, name, _, _, _, _) -> name
435+
| File(_, _, name, _, _) -> name
386436
| PackageReference(_, _, name, _) ->
387437
if name.ToLowerInvariant().EndsWith(".dll") then
388438
name.Substring(0, name.Length - 4)
@@ -455,7 +505,7 @@ module SolutionExplorer =
455505

456506
let command =
457507
match element with
458-
| File(_, p, _, _, _, _, _) ->
508+
| File(_, p, _, _, _) ->
459509
let c = createEmpty<Command>
460510
c.command <- "vscode.open"
461511
c.title <- "open"
@@ -492,7 +542,7 @@ module SolutionExplorer =
492542

493543
let icon, resourceUri =
494544
match element with
495-
| File(_, path, _, _, _, _, _)
545+
| File(_, path, _, _, _)
496546
| ProjectNotLoaded(_, path, _)
497547
| ProjectLoading(_, path, _)
498548
| ProjectFailedToLoad(_, path, _, _)
@@ -533,7 +583,7 @@ module SolutionExplorer =
533583
| PackageReference(_, _, _, pp)
534584
| ProjectReference(_, _, _, pp) -> Some(label ti + "||" + pp)
535585
| Folder _ -> None
536-
| File(_, _, _, _, pp, _, _) ->
586+
| File(_, _, _, _, pp) ->
537587
(resourceUri
538588
|> Option.map (fun u -> (label ti + "||" + u.toString () + "||" + pp)))
539589
| _ -> (resourceUri |> Option.map (fun u -> (label ti + "||" + u.toString ())))
@@ -631,7 +681,7 @@ module SolutionExplorer =
631681

632682
let rec private getModelPerFile (model: Model) : (string * Model) list =
633683
match model with
634-
| File(_, path, _, _, _, _, _)
684+
| File(_, path, _, _, _)
635685
| ProjectNotLoaded(_, path, _)
636686
| ProjectLoading(_, path, _)
637687
| ProjectFailedToLoad(_, path, _, _)
@@ -743,7 +793,7 @@ module SolutionExplorer =
743793
| Folder _
744794
| PackageReference _
745795
| ProjectReference _ -> false
746-
| File(_, filePath, _, _, _, _, _) ->
796+
| File(_, filePath, _, _, _) ->
747797
let projDir = node.path.dirname proj
748798
// Need to compute the relative path from the project in order to match the user input
749799
let relativeFilePathFromProject = node.path.relative (projDir, filePath)
@@ -771,7 +821,7 @@ module SolutionExplorer =
771821
let rec private tryFindParentProject (model: Model) =
772822
match model with
773823
| Project _ -> Some model
774-
| File(parent, _, _, _, _, _, _) ->
824+
| File(parent, _, _, _, _) ->
775825
match parent.Value with
776826
| Some parent -> tryFindParentProject parent
777827
| None -> None
@@ -910,7 +960,7 @@ module SolutionExplorer =
910960
"fsharp.explorer.moveUp",
911961
objfy2 (fun m ->
912962
match unbox m with
913-
| File(_, _, name, Some virtPath, proj, _, _) -> FsProjEdit.moveFileUpPath proj virtPath
963+
| File(_, _, name, Some virtPath, proj) -> FsProjEdit.moveFileUpPath proj virtPath
914964
| _ -> undefined
915965
|> ignore
916966

@@ -922,7 +972,7 @@ module SolutionExplorer =
922972
"fsharp.explorer.moveDown",
923973
objfy2 (fun m ->
924974
match unbox m with
925-
| File(_, _, name, Some virtPath, proj, _, _) -> FsProjEdit.moveFileDownPath proj virtPath
975+
| File(_, _, name, Some virtPath, proj) -> FsProjEdit.moveFileDownPath proj virtPath
926976
| _ -> undefined
927977
|> ignore
928978

@@ -934,7 +984,7 @@ module SolutionExplorer =
934984
"fsharp.explorer.removeFile",
935985
objfy2 (fun m ->
936986
match unbox m with
937-
| File(_, filePath, _, _, proj, _, _) ->
987+
| File(_, filePath, _, _, proj) ->
938988
promise {
939989
let projDir = node.path.dirname proj
940990
// Need to compute the relative path from the project in order to match the user input
@@ -955,7 +1005,7 @@ module SolutionExplorer =
9551005
"fsharp.explorer.renameFile",
9561006
objfy2 (fun m ->
9571007
match unbox m with
958-
| File(parent, filePath, _, Some virtualPath, _, _, _) ->
1008+
| File(parent, filePath, _, Some virtualPath, _) ->
9591009
match parent.Value with
9601010
| Some model ->
9611011
match tryFindParentProject model with
@@ -993,7 +1043,7 @@ module SolutionExplorer =
9931043
"fsharp.explorer.addAbove",
9941044
objfy2 (fun m ->
9951045
match unbox m with
996-
| File(parent, _, _, Some virtPath, _, _, _) ->
1046+
| File(parent, _, _, Some virtPath, _) ->
9971047
match parent.Value with
9981048
| Some model ->
9991049
match tryFindParentProject model with
@@ -1017,7 +1067,7 @@ module SolutionExplorer =
10171067
"fsharp.explorer.addBelow",
10181068
objfy2 (fun m ->
10191069
match unbox m with
1020-
| File(parent, _, _, Some virtPath, _, _, _) ->
1070+
| File(parent, _, _, Some virtPath, _) ->
10211071
match parent.Value with
10221072
| Some model ->
10231073
match tryFindParentProject model with

0 commit comments

Comments
 (0)