Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Allow selecting fsproj files into workspace #1955

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions src/Components/MSBuild.fs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ module MSBuild =
let buildTaskListForSolution (s: WorkspacePeekFound) : JS.Promise<MSBuildTask seq> =
promise {
match s with
| WorkspacePeekFound.Fsproj _ -> return Seq.empty
| WorkspacePeekFound.Directory _ -> return Seq.empty
| WorkspacePeekFound.Solution({ Path = p }) ->
let! dotnet = dotnetBinary ()
Expand Down
5 changes: 5 additions & 0 deletions src/Components/SolutionExplorer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,11 @@ module SolutionExplorer =
let result = Workspace items
setParentRefs items result
result
| WorkspacePeekFound.Fsproj proj ->
let result = getProjItem proj.Fsproj
let root = Workspace [ result ]
setParentRef result root
root

let private getSolution () =
Project.getLoadedSolution () |> Option.map getSolutionModel
Expand Down
3 changes: 3 additions & 0 deletions src/Core/DTO.fs
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,11 @@ module DTO =
type WorkspacePeek = { Found: WorkspacePeekFound[] }

and WorkspacePeekFound =
| Fsproj of WorkspacePeekFoundFsproj
| Directory of WorkspacePeekFoundDirectory
| Solution of WorkspacePeekFoundSolution
and WorkspacePeekFoundFsproj =
{ Fsproj: string }

and WorkspacePeekFoundDirectory =
{ Directory: string; Fsprojs: string[] }
Expand Down
14 changes: 9 additions & 5 deletions src/Core/LanguageService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -516,22 +516,26 @@ Consider:
Kind = kind }
| None -> None

let mapFound (f: obj) : WorkspacePeekFound option =
let mapFound (f: obj) : WorkspacePeekFound array =
let data = f?Data

match f?Type |> unbox with
| "directory" -> Some(WorkspacePeekFound.Directory(data |> unbox))
| "directory" ->
let folderPeek = [|WorkspacePeekFound.Directory(data |> unbox)|]
let projectPeeks = data?Fsprojs |> unbox |> Array.map (fun p -> WorkspacePeekFound.Fsproj({ Fsproj = p }))

Array.concat [|projectPeeks;folderPeek|]
| "solution" ->
let sln =
{ WorkspacePeekFoundSolution.Path = data?Path |> unbox
Configurations = data?Configurations |> unbox
Items = data?Items |> unbox |> Array.choose mapItem }

Some(WorkspacePeekFound.Solution sln)
| _ -> None
[|WorkspacePeekFound.Solution sln|]
| _ -> [||]

let parse (ws: obj) =
{ WorkspacePeek.Found = ws?Found |> unbox |> Array.choose mapFound }
{ WorkspacePeek.Found = ws?Found |> unbox |> Array.map mapFound |> Array.concat }

match client with
| None -> Promise.empty
Expand Down
82 changes: 55 additions & 27 deletions src/Core/Project.fs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ module Project =

sln.Items |> Array.collect getProjs |> Array.toList
| Some(WorkspacePeekFound.Directory dir) -> dir.Fsprojs |> Array.toList
| Some(WorkspacePeekFound.Fsproj fsproj) -> [ fsproj.Fsproj ]


let getNotLoaded () =
Expand Down Expand Up @@ -251,6 +252,7 @@ module Project =
match loadedWorkspace with
| None -> Array.empty
| Some(WorkspacePeekFound.Directory dir) -> dir.Fsprojs
| Some(WorkspacePeekFound.Fsproj fsproj) -> [| fsproj.Fsproj |]
| Some(WorkspacePeekFound.Solution sln) -> sln.Items |> Array.collect foldFsproj |> Array.map fst

let loadingInProgress p =
Expand Down Expand Up @@ -308,6 +310,7 @@ module Project =
type ConfiguredWorkspace =
| Solution of path: string
| Directory of path: string
| Fsproj of path: string

module private CurrentWorkspaceConfiguration =
let private key = "FSharp.workspacePath"
Expand All @@ -322,6 +325,8 @@ module Project =

if value.ToLowerInvariant().EndsWith(".sln") then
ConfiguredWorkspace.Solution fullPath
else if value.ToLowerInvariant().EndsWith(".fsproj") then
ConfiguredWorkspace.Fsproj fullPath
else
ConfiguredWorkspace.Directory fullPath

Expand All @@ -333,6 +338,12 @@ module Project =
not (isNull stats) && (stats.isDirectory ())
with _ ->
false
| ConfiguredWorkspace.Fsproj fsproj ->
try
let stats = node.fs.statSync (U2.Case1 fsproj)
not (isNull stats) && (stats.isFile ())
with _ ->
false
| ConfiguredWorkspace.Solution sln ->
try
let stats = node.fs.statSync (U2.Case1 sln)
Expand Down Expand Up @@ -373,6 +384,7 @@ module Project =
match value with
| ConfiguredWorkspace.Solution path -> path
| ConfiguredWorkspace.Directory path -> path
| ConfiguredWorkspace.Fsproj path -> path

let private isConfiguredInWorkspace () =
match getStringFromWorkspaceConfig () with
Expand Down Expand Up @@ -400,6 +412,7 @@ module Project =
let setFromPeek (value: WorkspacePeekFound) =
match value with
| WorkspacePeekFound.Directory dir -> ConfiguredWorkspace.Directory dir.Directory
| WorkspacePeekFound.Fsproj fsproj -> ConfiguredWorkspace.Fsproj fsproj.Fsproj
| WorkspacePeekFound.Solution sln -> ConfiguredWorkspace.Solution sln.Path
|> set

Expand All @@ -419,6 +432,7 @@ module Project =
| ConfiguredWorkspace.Directory valueDir, WorkspacePeekFound.Directory peekDir ->
removeEndSlash valueDir = removeEndSlash peekDir.Directory
| ConfiguredWorkspace.Solution valueSln, WorkspacePeekFound.Solution peekSln -> valueSln = peekSln.Path
| ConfiguredWorkspace.Fsproj valueFsproj, WorkspacePeekFound.Fsproj peekFsproj -> valueFsproj = peekFsproj.Fsproj
| _ -> false

let tryFind (value: ConfiguredWorkspace option) (found: WorkspacePeekFound list) =
Expand All @@ -444,6 +458,12 @@ module Project =
item.label <- sprintf "%s%s" check dir.Directory
item.description <- Some(sprintf "Directory with %i projects" dir.Fsprojs.Length)
item
| WorkspacePeekFound.Fsproj fsproj ->
let relative = node.path.relative (workspace.rootPath.Value, fsproj.Fsproj)
let item = createEmpty<QuickPickItem>
item.label <- sprintf "%s%s" check relative
item.description <- Some(sprintf "Single project")
item
| WorkspacePeekFound.Solution sln ->
let relative = node.path.relative (workspace.rootPath.Value, sln.Path)
let item = createEmpty<QuickPickItem>
Expand Down Expand Up @@ -556,12 +576,12 @@ module Project =
return []
else
let! ws = LanguageService.workspacePeek workspace.rootPath.Value deepLevel (excluded |> List.ofArray)

return
ws.Found
|> Array.sortBy (fun x ->
match x with
| WorkspacePeekFound.Solution sln -> countProjectsInSln sln
| WorkspacePeekFound.Fsproj _ -> 0
| WorkspacePeekFound.Directory _ -> -1)
|> Array.rev
|> List.ofArray
Expand All @@ -572,33 +592,39 @@ module Project =
let! ws = workspacePeek ()
let configured = CurrentWorkspaceConfiguration.get ()
let configuredPeek = CurrentWorkspaceConfiguration.tryFind configured ws

match configuredPeek with
| Some peek ->
// If a workspace is configured, use it
return Some peek
| None ->
let! choosen = pickFSACWorkspace ws None
return choosen

// TODO: Rewrite this so that the sln isn't always chosen, maybe add a config?

// match configuredPeek with
// | Some peek ->
// // If a workspace is configured, use it
// return Some peek
// | None ->

// prefer the sln, load directly the first one, otherwise ask
let slns =
ws
|> List.choose (fun x ->
match x with
| WorkspacePeekFound.Solution _ -> Some x
| _ -> None)

let! choosen =
match slns with
| [] ->
ws
|> List.tryPick (fun x ->
match x with
| WorkspacePeekFound.Directory _ -> Some x
| _ -> None)
|> Promise.lift
| [ sln ] -> Promise.lift (Some sln)
| _ -> pickFSACWorkspace ws None

return choosen
// let slns =
// ws
// |> List.choose (fun x ->
// match x with
// | WorkspacePeekFound.Solution _ -> Some x
// | _ -> None)

// let! choosen =
// match slns with
// | [] ->
// ws
// |> List.tryPick (fun x ->
// match x with
// | WorkspacePeekFound.Directory _ -> Some x
// | _ -> None)
// |> Promise.lift
// | [ sln ] -> Promise.lift (Some sln)
// | _ -> pickFSACWorkspace ws None

// let! choosen = pickFSACWorkspace ws None
// return choosen
}

let handleProjectParsedNotification res =
Expand Down Expand Up @@ -650,10 +676,12 @@ module Project =
let projs =
match x with
| WorkspacePeekFound.Directory dir -> dir.Fsprojs
| WorkspacePeekFound.Fsproj fsproj -> [| fsproj.Fsproj |]
| WorkspacePeekFound.Solution sln -> sln.Items |> Array.collect foldFsproj |> Array.map fst

match x with
| WorkspacePeekFound.Solution _ -> setAnyProjectContext true
| WorkspacePeekFound.Fsproj _ -> setAnyProjectContext false
| WorkspacePeekFound.Directory _ when not (projs |> Array.isEmpty) -> setAnyProjectContext true
| _ -> ()

Expand Down