@@ -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