Skip to content

Commit

Permalink
add a way to efficiently map many project options to FCS options at once
Browse files Browse the repository at this point in the history
  • Loading branch information
baronfel committed Jul 23, 2022
1 parent 0154c26 commit bfcb0f1
Showing 1 changed file with 48 additions and 23 deletions.
71 changes: 48 additions & 23 deletions src/Ionide.ProjInfo.FCS/Library.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,57 @@ module FCS =

FSharpReferencedProject.CreatePortableExecutable(p.TargetPath, getStamp, getStream)

let rec mapToFSharpProjectOptions (projectOptions: ProjectOptions) (allKnownProjects: ProjectOptions seq) : FSharpProjectOptions =
let private makeFCSOptions mapProjectToReference (project: ProjectOptions) =
{ ProjectId = None
ProjectFileName = projectOptions.ProjectFileName
SourceFiles = List.toArray projectOptions.SourceFiles
OtherOptions = List.toArray projectOptions.OtherOptions
ReferencedProjects =
projectOptions.ReferencedProjects
|> List.toArray
|> Array.choose (fun d ->
let knownProject = allKnownProjects |> Seq.tryFind (fun n -> n.ProjectFileName = d.ProjectFileName)

let isDotnetProject (knownProject: ProjectOptions option) =
match knownProject with
| Some p -> (p.ProjectFileName.EndsWith(".csproj") || p.ProjectFileName.EndsWith(".vbproj")) && File.Exists p.TargetPath
| None -> false

if d.ProjectFileName.EndsWith ".fsproj" then
knownProject
|> Option.map (fun p -> FSharpReferencedProject.CreateFSharp(p.TargetPath, mapToFSharpProjectOptions p allKnownProjects))
elif isDotnetProject knownProject then
knownProject |> Option.map loadFromDotnetDll
else
None)
ProjectFileName = project.ProjectFileName
SourceFiles = List.toArray project.SourceFiles
OtherOptions = List.toArray project.OtherOptions
ReferencedProjects = project.ReferencedProjects |> List.toArray |> Array.choose mapProjectToReference
IsIncompleteTypeCheckEnvironment = false
UseScriptResolutionRules = false
LoadTime = projectOptions.LoadTime
LoadTime = project.LoadTime
UnresolvedReferences = None // it's always None
OriginalLoadReferences = [] // it's always empty list
Stamp = None }

let rec private makeProjectReference isKnownProject makeFSharpProjectReference (p: ProjectReference) : FSharpReferencedProject option =
let knownProject = isKnownProject p

let isDotnetProject (knownProject: ProjectOptions option) =
match knownProject with
| Some p -> (p.ProjectFileName.EndsWith(".csproj") || p.ProjectFileName.EndsWith(".vbproj")) && File.Exists p.TargetPath
| None -> false

if p.ProjectFileName.EndsWith ".fsproj" then
knownProject
|> Option.map (fun p ->
let theseOptions = makeFSharpProjectReference p
FSharpReferencedProject.CreateFSharp(p.TargetPath, theseOptions))
elif isDotnetProject knownProject then
knownProject |> Option.map loadFromDotnetDll
else
None

let mapManyOptions (allKnownProjects: ProjectOptions seq) : FSharpProjectOptions seq =
seq {
let dict = System.Collections.Concurrent.ConcurrentDictionary<ProjectOptions, FSharpProjectOptions>()

let isKnownProject (p: ProjectReference) =
allKnownProjects |> Seq.tryFind (fun kp -> kp.ProjectFileName = p.ProjectFileName)

let rec makeFSharpProjectReference (p: ProjectOptions) =
let factory = makeProjectReference isKnownProject makeFSharpProjectReference
dict.GetOrAdd(p, (fun p -> makeFCSOptions factory p))

for project in allKnownProjects do
let thisProject =
dict.GetOrAdd(project, (fun p -> makeFCSOptions (makeProjectReference isKnownProject makeFSharpProjectReference) p))

yield thisProject
}

let rec mapToFSharpProjectOptions (projectOptions: ProjectOptions) (allKnownProjects: ProjectOptions seq) : FSharpProjectOptions =
let isKnownProject (d: ProjectReference) =
allKnownProjects |> Seq.tryFind (fun n -> n.ProjectFileName = d.ProjectFileName)

makeFCSOptions (makeProjectReference isKnownProject (fun p -> mapToFSharpProjectOptions p allKnownProjects)) projectOptions

0 comments on commit bfcb0f1

Please sign in to comment.