@@ -28,34 +28,35 @@ module SolutionExplorer =
2828 | ProjectLanguageNotSupported of parent : Model option ref * path : string * name : string
2929 | Project of parent : Model option ref * path : string * name : string * Files : Model list * ProjectReferencesList : Model * ReferenceList : Model * isExe : bool * project : DTO.Project
3030 | Folder of parent : Model option ref * name : string * path : string * Files : Model list * projectPath : string
31- | File of parent : Model option ref * path : string * name : string * projectPath : string
31+ | File of parent : Model option ref * path : string * name : string * virtualPath : string option * projectPath : string
3232 | PackageReference of parent : Model option ref * path : string * name : string * projectPath : string
3333 | ProjectReference of parent : Model option ref * path : string * name : string * projectPath : string
3434
3535 type NodeEntry =
3636 { Key : string
3737 FilePath: string
38- Children : Dictionary < string , NodeEntry > }
38+ VirtualPath : string
39+ mutable Children : NodeEntry list }
3940
4041 let inline pathCombine a b =
4142 a + node.path.sep + b
4243
4344 let add ' root ( virtualPath : string ) filepath =
4445 let rec addhelper state items =
45- match items with
46- | [ ] -> state
47- | [ key ] ->
48- if not ( state.Children.ContainsKey key ) then
49- let x = { Key = key; FilePath = filepath; Children = new Dictionary <_,_>() }
50- state.Children.Add ( key , x )
46+ match items, state.Children with
47+ | [ ], _ -> state
48+ | [ key ], children when children |> List.exists ( fun c -> c.Key = key ) -> state
49+ | [ key ], _ ->
50+ let x = { Key = key; FilePath = filepath; VirtualPath = virtualPath ; Children = [] }
51+ state.Children <- x :: state.Children
5152 state
52- | dirName :: xs ->
53- if not ( state.Children.ContainsKey dirName ) then
54- let dirPath = pathCombine state.FilePath dirName
55- let x = { Key = dirName ; FilePath = dirPath ; Children = new Dictionary <_,_>() }
56- state.Children.Add ( dirName, x )
57- let item = state.Children.[ dirName ]
58- addhelper item xs
53+ | dirName :: xs, lastFileOrDir :: _ when dirName = lastFileOrDir.Key ->
54+ addhelper lastFileOrDir xs
55+ | dirName :: xs , _ ->
56+ let dirPath = pathCombine state. FilePath dirName
57+ let x = { Key = dirName; FilePath = dirPath ; VirtualPath = virtualPath ; Children = [] }
58+ state.Children <- x :: state.Children
59+ addhelper x xs
5960
6061 virtualPath.Split( '/' )
6162 |> List.ofArray
@@ -77,7 +78,7 @@ module SolutionExplorer =
7778 | ProjectLanguageNotSupported ( parent, _, _) -> parent
7879 | Project ( parent, _, _, _, _, _, _, _) -> parent
7980 | Folder ( parent, _, _, _, _) -> parent
80- | File ( parent, _, _, _) -> parent
81+ | File ( parent, _, _, _, _ ) -> parent
8182 | PackageReference ( parent, _, _, _) -> parent
8283 | ProjectReference ( parent, _, _, _) -> parent
8384
@@ -104,23 +105,24 @@ module SolutionExplorer =
104105*)
105106
106107 let rec toModel ( projPath : string ) ( entry : NodeEntry ) =
107- if entry.Children.Count > 0 then
108+ if entry.Children.Length > 0 then
108109 let childs =
109110 entry.Children
110- |> Seq.map ( fun n -> toModel projPath n.Value )
111+ |> Seq.map ( toModel projPath)
111112 |> Seq.toList
112113 let result = Folder( ref None, entry.Key, entry.FilePath, childs, projPath)
113114 setParentRefs childs result
114115 result
115116 else
116- File( ref None, entry.FilePath, entry.Key, projPath)
117+ File( ref None, entry.FilePath, entry.Key, Some entry.VirtualPath , projPath)
117118
118119 let buildTree projPath ( files : ( string * string ) list ) =
119120 let projDir = dirName projPath
120- let entry = { Key = " " ; FilePath = projDir; Children = new Dictionary <_,_>() }
121+ let entry = { Key = " " ; FilePath = projDir; VirtualPath = " " ; Children = [] }
121122 files |> List.iter ( fun ( virtualPath , path ) -> add' entry virtualPath path)
122123 entry.Children
123- |> Seq.map ( fun n -> toModel projPath n.Value )
124+ |> Seq.rev
125+ |> Seq.map ( toModel projPath)
124126 |> Seq.toList
125127
126128 let private getProjectModel ( proj : Project ) =
@@ -206,7 +208,7 @@ module SolutionExplorer =
206208 | WorkspacePeekFoundSolutionItemKind.Folder folder ->
207209 let files =
208210 folder.Files
209- |> Array.map ( fun f -> Model.File ( ref None, f, node.path.basename( f), " " ))
211+ |> Array.map ( fun f -> Model.File ( ref None, f, node.path.basename( f), None , " " ))
210212 let items = folder.Items |> Array.map getItem
211213 let result = Model.WorkspaceFolder ( ref None, item.Name, ( Seq.append files items |> List.ofSeq))
212214 setParentRefs files result
@@ -250,7 +252,7 @@ module SolutionExplorer =
250252 ]
251253 | PackageReferenceList (_, refs, _) -> refs
252254 | ProjectReferencesList (_, refs, _) -> refs
253- | Folder (_, _,_, files, _) -> files
255+ | Folder (_, _,_, files, _) -> files |> List.rev
254256 | File _ -> []
255257 | PackageReference _ -> []
256258 | ProjectReference _ -> []
@@ -269,7 +271,7 @@ module SolutionExplorer =
269271 | PackageReferenceList _ -> " Package References"
270272 | ProjectReferencesList (_, refs, _) -> " Project References"
271273 | Folder (_, n,_, _, _) -> n
272- | File (_, _, name, _) -> name
274+ | File (_, _, name, _, _ ) -> name
273275 | PackageReference (_, _, name, _) ->
274276 if name.ToLowerInvariant() .EndsWith( " .dll" ) then
275277 name.Substring( 0 , name.Length - 4 )
@@ -335,7 +337,7 @@ module SolutionExplorer =
335337
336338 let command =
337339 match node with
338- | File (_, p, _, _) ->
340+ | File (_, p, _, _, _ ) ->
339341 let c = createEmpty< Command>
340342 c.command <- " vscode.open"
341343 c.title <- " open"
@@ -371,7 +373,7 @@ module SolutionExplorer =
371373
372374 let icon , resourceUri =
373375 match node with
374- | File (_, path, _, _)
376+ | File (_, path, _, _, _ )
375377 | Project (_, path, _, _, _, _, _, _)
376378 | ProjectNotLoaded (_, path, _)
377379 | ProjectLoading (_, path, _)
@@ -398,7 +400,9 @@ module SolutionExplorer =
398400 match node with
399401 | PackageReferenceList (_, _, pp) | ProjectReferencesList (_, _, pp) | PackageReference (_, _, _, pp) | ProjectReference (_, _, _, pp) ->
400402 Some (( defaultArg ti.label " " ) + " ||" + pp)
401- | Folder (_, _,_, _, pp) | File (_, _, _, pp) ->
403+ | Folder _ ->
404+ None
405+ | File (_, _, _, _, pp) ->
402406 ( resourceUri |> Option.map( fun u -> ( defaultArg ti.label " " ) + " ||" + u.toString() + " ||" + pp))
403407 | _ ->
404408 ( resourceUri |> Option.map( fun u -> ( defaultArg ti.label " " ) + " ||" + u.toString()))
@@ -463,7 +467,7 @@ module SolutionExplorer =
463467
464468 let rec private getModelPerFile ( model : Model ) : ( string * Model ) list =
465469 match model with
466- | File (_, path, _, _)
470+ | File (_, path, _, _, _ )
467471 | ProjectNotLoaded (_, path, _)
468472 | ProjectLoading (_, path, _)
469473 | ProjectFailedToLoad (_, path, _, _)
@@ -581,35 +585,35 @@ module SolutionExplorer =
581585
582586 commands.registerCommand( " fsharp.explorer.moveUp" , objfy2 ( fun m ->
583587 match unbox m with
584- | File (_, _, name, proj) -> FsProjEdit.moveFileUpPath proj name
588+ | File (_, _, name, Some virtPath , proj) -> FsProjEdit.moveFileUpPath proj virtPath
585589 | _ -> undefined
586590 )) |> context.subscriptions.Add
587591
588592 commands.registerCommand( " fsharp.explorer.moveDown" , objfy2 ( fun m ->
589593 match unbox m with
590- | File (_, _, name, proj) -> FsProjEdit.moveFileDownPath proj name
594+ | File (_, _, name, Some virtPath , proj) -> FsProjEdit.moveFileDownPath proj virtPath
591595 | _ -> undefined
592596 )) |> context.subscriptions.Add
593597
594598 commands.registerCommand( " fsharp.explorer.removeFile" , objfy2 ( fun m ->
595599 match unbox m with
596- | File (_, _, name, proj) -> FsProjEdit.removeFilePath proj name
600+ | File (_, _, name, Some virtPath , proj) -> FsProjEdit.removeFilePath proj virtPath
597601 | _ -> undefined
598602 )) |> context.subscriptions.Add
599603
600604
601605 commands.registerCommand( " fsharp.explorer.addAbove" , objfy2 ( fun m ->
602606 match unbox m with
603- | File (_, _, name, proj) ->
607+ | File (_, _, name, Some virtPath , proj) ->
604608 let opts = createEmpty< InputBoxOptions>
605609 opts.placeHolder <- Some " new.fs"
606- opts.prompt <- Some " New file name, relative to project file"
610+ opts.prompt <- Some " New file name, relative to selected file"
607611 opts.value <- Some " new.fs"
608612 window.showInputBox( opts)
609613 |> Promise.bind ( fun file ->
610614 if JS.isDefined file then
611615 let file ' = handleUntitled file
612- FsProjEdit.addFileAbove proj name file'
616+ FsProjEdit.addFileAbove proj virtPath file'
613617 else
614618 Promise.empty
615619 )
@@ -619,16 +623,16 @@ module SolutionExplorer =
619623
620624 commands.registerCommand( " fsharp.explorer.addBelow" , objfy2 ( fun m ->
621625 match unbox m with
622- | File (_, fr_ om, name, proj) ->
626+ | File (_, fr_ om, name, Some virtPath , proj) ->
623627 let opts = createEmpty< InputBoxOptions>
624628 opts.placeHolder <- Some " new.fs"
625- opts.prompt <- Some " New file name, relative to project file"
629+ opts.prompt <- Some " New file name, relative to selected file"
626630 opts.value <- Some " new.fs"
627631 window.showInputBox( opts)
628632 |> Promise.map ( fun file ->
629633 if JS.isDefined file then
630634 let file ' = handleUntitled file
631- FsProjEdit.addFileBelow proj name file'
635+ FsProjEdit.addFileBelow proj virtPath file'
632636 else
633637 Promise.empty
634638 )
@@ -641,7 +645,7 @@ module SolutionExplorer =
641645 | Project (_, proj, _, _,_,_,_,_) ->
642646 let opts = createEmpty< InputBoxOptions>
643647 opts.placeHolder <- Some " new.fs"
644- opts.prompt <- Some " New file name, relative to opened directory "
648+ opts.prompt <- Some " New file name, relative to project file "
645649 opts.value <- Some " new.fs"
646650 window.showInputBox( opts)
647651 |> Promise.map ( fun file ->
0 commit comments