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

Allow global properties to be provided to project loaders #107

Merged
merged 4 commits into from
Apr 16, 2021
Merged
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
19 changes: 15 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.52.0] - 2021-04-13

### Changed

- [Allow global properties to be provided to project loaders](https://github.com/ionide/proj-info/pull/107)

## [0.51.0] - 2021-03-15

* Change the order of calls so that FSAC doesn't have a deadlock with its current usage of this library
### Changed

- Change the order of calls so that FSAC doesn't have a deadlock with its current usage of this library

## [0.50.0] - 2021-03-13

* Introduce a pluggable abstraction for creating workspaces to allow for independent experimentation
* Introduce a workspace implementation for MsBuild Graph Build mode, which should be a large performance boost for consumers
* introduce debouncing to prevent rebuilds when invoked multiple times in a short timeframe
### Changed

- Introduce a pluggable abstraction for creating workspaces to allow for independent experimentation
- Introduce a workspace implementation for MsBuild Graph Build mode, which should be a large performance boost for consumers
- introduce debouncing to prevent rebuilds when invoked multiple times in a short timeframe

## [0.49.0] - 2021-03-03

Expand Down
40 changes: 23 additions & 17 deletions src/Ionide.ProjInfo/Library.fs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ module ProjectLoader =
else
[ logger ]

let getGlobalProps (path: string) (tfm: string option) =
let getGlobalProps (path: string) (tfm: string option) (globalProperties: (string * string) list)=
dict [ "ProvideCommandLineArgs", "true"
"DesignTimeBuild", "true"
"SkipCompilerExecution", "true"
Expand All @@ -91,19 +91,20 @@ module ProjectLoader =
"TargetFramework", tfm.Value
if path.EndsWith ".csproj" then
"NonExistentFile", Path.Combine("__NonExistentSubDir__", "__NonExistentFile__")
"DotnetProjInfo", "true" ]
"DotnetProjInfo", "true"
yield! globalProperties ]


let buildArgs =
[| "ResolvePackageDependenciesDesignTime"
"_GenerateCompileDependencyCache"
"CoreCompile" |]

let loadProject (path: string) (generateBinlog: bool) (ToolsPath toolsPath) =
let loadProject (path: string) (generateBinlog: bool) (ToolsPath toolsPath) globalProperties =
try
let tfm = getTfm path

let globalProperties = getGlobalProps path tfm
let globalProperties = getGlobalProps path tfm globalProperties

match System.Environment.GetEnvironmentVariable "DOTNET_HOST_PATH" with
| null
Expand All @@ -112,7 +113,7 @@ module ProjectLoader =

use pc = new ProjectCollection(globalProperties)

let pi = pc.LoadProject(path)
let pi = pc.LoadProject(path, globalProperties, toolsVersion=null)

use sw = new StringWriter()

Expand Down Expand Up @@ -343,10 +344,11 @@ module ProjectLoader =
/// <param name="path">Full path to the `.fsproj` file</param>
/// <param name="toolsPath">Path to MsBuild obtained from `ProjectLoader.init ()`</param>
/// <param name="generateBinlog">Enable Binary Log generation</param>
/// <param name="globalProperties">The global properties to use (e.g. Configuration=Release). Some additional global properties are pre-set by the tool</param>
/// <param name="customProperties">List of additional MsBuild properties that you want to obtain.</param>
/// <returns>Returns the record instance representing the loaded project or string containing error message</returns>
let getProjectInfo (path: string) (toolsPath: ToolsPath) (generateBinlog: bool) (customProperties: string list) : Result<Types.ProjectOptions, string> =
let loadedProject = loadProject path generateBinlog toolsPath
let getProjectInfo (path: string) (toolsPath: ToolsPath) (globalProperties: (string*string) list) (generateBinlog: bool) (customProperties: string list) : Result<Types.ProjectOptions, string> =
let loadedProject = loadProject path generateBinlog toolsPath globalProperties

match loadedProject with
| Success project -> getLoadedProjectInfo path customProperties project
Expand All @@ -369,7 +371,8 @@ type IWorkspaceLoader =
[<CLIEvent>]
abstract Notifications : IEvent<WorkspaceProjectState>

type WorkspaceLoaderViaProjectGraph private (toolsPath: ToolsPath) =
type WorkspaceLoaderViaProjectGraph private (toolsPath: ToolsPath, ?globalProperties: (string*string) list) =
let globalProperties = defaultArg globalProperties []
let logger = LogProvider.getLoggerFor<WorkspaceLoaderViaProjectGraph> ()
let loadingNotification = new Event<Types.WorkspaceProjectState>()

Expand All @@ -383,17 +386,19 @@ type WorkspaceLoaderViaProjectGraph private (toolsPath: ToolsPath) =
loadingNotification.Trigger(WorkspaceProjectState.Failed(p, ProjectNotFound(p)))
None

let projectInstanceFactory projectPath globalProperties (projectCollection: ProjectCollection) =
let projectInstanceFactory projectPath (_globalProperties: IDictionary<string,string>) (projectCollection: ProjectCollection) =
let tfm = ProjectLoader.getTfm projectPath
ProjectInstance(projectPath, ProjectLoader.getGlobalProps projectPath tfm, null, projectCollection)
//let globalProperties = globalProperties |> Seq.toList |> List.map (fun (KeyValue(k,v)) -> (k,v))
let globalProperties = ProjectLoader.getGlobalProps projectPath tfm globalProperties
ProjectInstance(projectPath, globalProperties, toolsVersion=null, projectCollection=projectCollection)

let projectGraphProjs (paths: string seq) =

handleProjectGraphFailures
<| fun () ->
paths |> Seq.iter (fun p -> loadingNotification.Trigger(WorkspaceProjectState.Loading p))
let entryPoints = paths |> Seq.map ProjectGraphEntryPoint
ProjectGraph(entryPoints, ProjectCollection.GlobalProjectCollection, projectInstanceFactory)
ProjectGraph(entryPoints, projectCollection=ProjectCollection.GlobalProjectCollection, projectInstanceFactory=projectInstanceFactory)

let projectGraphSln (path: string) =
handleProjectGraphFailures
Expand Down Expand Up @@ -541,10 +546,11 @@ type WorkspaceLoaderViaProjectGraph private (toolsPath: ToolsPath) =
this.LoadSln(sln, customProperties, false)


static member Create(toolsPath: ToolsPath) =
WorkspaceLoaderViaProjectGraph(toolsPath) :> IWorkspaceLoader
static member Create(toolsPath: ToolsPath, ?globalProperties) =
WorkspaceLoaderViaProjectGraph(toolsPath, ?globalProperties=globalProperties) :> IWorkspaceLoader

type WorkspaceLoader private (toolsPath: ToolsPath) =
type WorkspaceLoader private (toolsPath: ToolsPath, ?globalProperties: (string * string) list) =
let globalProperties = defaultArg globalProperties []
let loadingNotification = new Event<Types.WorkspaceProjectState>()


Expand All @@ -561,7 +567,7 @@ type WorkspaceLoader private (toolsPath: ToolsPath) =
cache |> Seq.map (fun n -> n.Value) |> Seq.toList

let rec loadProject p =
let res = ProjectLoader.getProjectInfo p toolsPath generateBinlog customProperties
let res = ProjectLoader.getProjectInfo p toolsPath globalProperties generateBinlog customProperties

match res with
| Ok project ->
Expand Down Expand Up @@ -644,8 +650,8 @@ type WorkspaceLoader private (toolsPath: ToolsPath) =



static member Create(toolsPath: ToolsPath) =
WorkspaceLoader(toolsPath) :> IWorkspaceLoader
static member Create(toolsPath: ToolsPath, ?globalProperties) =
WorkspaceLoader(toolsPath, ?globalProperties=globalProperties) :> IWorkspaceLoader

type ProjectViewerTree =
{ Name: string
Expand Down
22 changes: 15 additions & 7 deletions test/Ionide.ProjInfo.Tests/Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ open Ionide.ProjInfo
open Expecto.Logging.Message
open FSharp.Compiler.SourceCodeServices

#nowarn "25"

let RepoDir = (__SOURCE_DIRECTORY__ / ".." / "..") |> Path.GetFullPath
let ExamplesDir = RepoDir / "test" / "examples"
let TestRunDir = RepoDir / "test" / "testrun_ws"
Expand Down Expand Up @@ -140,10 +142,10 @@ module ExpectNotification =
let watchNotifications logger loader =
NotificationWatcher(loader, logNotification logger)

let testSample2 toolsPath workspaceLoader (workspaceFactory: ToolsPath -> IWorkspaceLoader) =
let testSample2 toolsPath workspaceLoader isRelease (workspaceFactory: ToolsPath * (string * string) list -> IWorkspaceLoader) =
testCase
|> withLog
(sprintf "can load sample2 - %s" workspaceLoader)
(sprintf "can load sample2 - %s - isRelease is %b" workspaceLoader isRelease)
(fun logger fs ->
let testDir = inDir fs "load_sample2"
copyDirFromAssets fs ``sample2 NetSdk library``.ProjDir testDir
Expand All @@ -153,7 +155,9 @@ let testSample2 toolsPath workspaceLoader (workspaceFactory: ToolsPath -> IWorks

dotnet fs [ "restore"; projPath ] |> checkExitCodeZero

let loader = workspaceFactory toolsPath
let config = if isRelease then "Release" else "Debug"
let props = [("Configuration", config)]
let loader = workspaceFactory (toolsPath, props)

let watcher = watchNotifications logger loader

Expand All @@ -168,8 +172,10 @@ let testSample2 toolsPath workspaceLoader (workspaceFactory: ToolsPath -> IWorks
let n1Parsed = parsed |> expectFind projPath "first is a lib"

let expectedSources =
[ projDir / "obj/Debug/netstandard2.0/n1.AssemblyInfo.fs"
projDir / "Library.fs" ]
[ projDir / ("obj/" + config + "/netstandard2.0/n1.AssemblyInfo.fs")
projDir / "Library.fs"
if isRelease then
projDir / "Other.fs" ]
|> List.map Path.GetFullPath

Expect.equal parsed.Length 1 "console and lib"
Expand Down Expand Up @@ -981,8 +987,10 @@ let tests toolsPath =
testSequenced
<| testList
"Main tests"
[ testSample2 toolsPath "WorkspaceLoader" WorkspaceLoader.Create
testSample2 toolsPath "WorkspaceLoaderViaProjectGraph" WorkspaceLoaderViaProjectGraph.Create
[ testSample2 toolsPath "WorkspaceLoader" false (fun (tools,props) -> WorkspaceLoader.Create(tools, globalProperties=props))
testSample2 toolsPath "WorkspaceLoader" true (fun (tools,props) -> WorkspaceLoader.Create(tools, globalProperties=props))
testSample2 toolsPath "WorkspaceLoaderViaProjectGraph" false (fun (tools,props) -> WorkspaceLoaderViaProjectGraph.Create(tools, globalProperties=props))
testSample2 toolsPath "WorkspaceLoaderViaProjectGraph" true (fun (tools,props) -> WorkspaceLoaderViaProjectGraph.Create(tools, globalProperties=props))
testSample3 toolsPath "WorkspaceLoader" WorkspaceLoader.Create testSample3WorkspaceLoaderExpected //- Sample 3 having issues, was also marked pending on old test suite
// testSample3 toolsPath "WorkspaceLoaderViaProjectGraph" WorkspaceLoaderViaProjectGraph.Create testSample3GraphExpected //- Sample 3 having issues, was also marked pending on old test suite
testSample4 toolsPath "WorkspaceLoader" WorkspaceLoader.Create
Expand Down
3 changes: 2 additions & 1 deletion test/examples/sample2-netsdk-lib/n1/n1.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="Library.fs" />
<Compile Include="Library.fs" />
<Compile Include="Other.fs" Condition="'$(Configuration)' == 'Release'"/>
</ItemGroup>

</Project>