提交 322d27f0 编写于 作者: L latkin

Proper handling of VSUTDCF options in up-to-date check, and safer...

Proper handling of VSUTDCF options in up-to-date check, and safer TryGetActiveConfigurationAndPlatform

 - Use `IVsSolutionBuildManager5.FindActiveProjectCfgName` instead of `IVsSolutionBuildManager2.FindActiveProjectCfg` in `TryGetActiveConfigurationAndPlatform`, as it is not sensitive to sync context
 - Give proper consideration to the VSUTDCF options flags passed to QueryStartUpToDateCheck

fixes #471
closes #479
上级 64c4ea61
......@@ -327,6 +327,58 @@ type UpToDate() =
Assert.IsFalse(config.IsFastUpToDateCheckEnabled())
))
[<Test>]
member public this.UTDOptionsFlags () =
this.MakeProjectAndDo(["file1.fs"], [], "", (fun project ->
let configNameDebugx86 = ConfigCanonicalName("Debug", "x86")
let debugConfigx86 = project.ConfigProvider.GetProjectConfiguration(configNameDebugx86)
let buildableConfig =
match debugConfigx86.get_BuildableProjectCfg() with
| 0, bc -> bc
| _ -> failwith "get_BuildableProjectCfg failed"
let testFlag flag expected =
let supported = Array.zeroCreate<int> 1
let ready = Array.zeroCreate<int> 1
buildableConfig.QueryStartUpToDateCheck(flag, supported, ready) |> ignore
Assert.IsTrue(supported.[0] = expected)
Assert.IsTrue(ready.[0] = expected)
[ VSConstants.VSUTDCF_DTEEONLY, 1
VSConstants.VSUTDCF_PACKAGE, 0
VSConstants.VSUTDCF_PRIVATE, 1
VSConstants.VSUTDCF_REBUILD, 1 ]
|> List.iter (fun (flag, expected) -> testFlag flag expected)
))
[<Test>]
member public this.UTDOptionsFlagsUTDDisabled () =
this.MakeProjectAndDo(["file1.fs"], [], @"
<PropertyGroup>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
", (fun project ->
let configNameDebugx86 = ConfigCanonicalName("Debug", "x86")
let debugConfigx86 = project.ConfigProvider.GetProjectConfiguration(configNameDebugx86)
let buildableConfig =
match debugConfigx86.get_BuildableProjectCfg() with
| 0, bc -> bc
| _ -> failwith "get_BuildableProjectCfg failed"
let testFlag flag expected =
let supported = Array.zeroCreate<int> 1
let ready = Array.zeroCreate<int> 1
buildableConfig.QueryStartUpToDateCheck(flag, supported, ready) |> ignore
Assert.AreEqual(supported.[0], expected)
Assert.AreEqual(ready.[0], expected)
[ VSConstants.VSUTDCF_DTEEONLY, 1
VSConstants.VSUTDCF_PACKAGE, 0
VSConstants.VSUTDCF_PRIVATE, 0
VSConstants.VSUTDCF_REBUILD, 0 ]
|> List.iter (fun (flag, expected) -> testFlag flag expected)
))
[<TestFixture>]
type ``UpToDate PreserveNewest`` () =
......
......@@ -1591,7 +1591,8 @@ internal bool IsUpToDate(OutputWindowLogger logger, bool testing)
// in batch build it is possible that config is out of sync.
// in this case, don't assume we are up to date
ConfigCanonicalName activeConfig = default(ConfigCanonicalName);
if(!Utilities.TryGetActiveConfigurationAndPlatform(ServiceProvider.GlobalProvider, this.project, out activeConfig) ||
if(!Utilities.TryGetActiveConfigurationAndPlatform(ServiceProvider.GlobalProvider, this.project.ProjectIDGuid, out activeConfig) ||
activeConfig != this.ConfigCanonicalName)
{
logger.WriteLine("Not up to date: active confic does not match project config. Active: {0} Project: {1}", activeConfig, this.ConfigCanonicalName);
......@@ -1836,12 +1837,21 @@ public virtual int QueryStartUpToDateCheck(uint options, int[] supported, int[]
CCITracing.TraceCall();
config.PrepareBuild(false);
int utdSupported = config.IsFastUpToDateCheckEnabled() ? 1 : 0;
// criteria (same as C# project system):
// - Fast UTD never enabled for package operations
// - Fast UTD always enabled for DTEE operations
// - Otherwise fast UTD enabled as long as it's not explicitly disabled by the project
bool utdSupported =
((options & VSConstants.VSUTDCF_PACKAGE) == 0) &&
(((options & VSConstants.VSUTDCF_DTEEONLY) != 0) || config.IsFastUpToDateCheckEnabled());
int utdSupportedFlag = utdSupported ? 1 : 0;
if (supported != null && supported.Length > 0)
supported[0] = utdSupported;
supported[0] = utdSupportedFlag;
if (ready != null && ready.Length > 0)
ready[0] = utdSupported;
ready[0] = utdSupportedFlag;
return VSConstants.S_OK;
}
......
......@@ -4150,7 +4150,7 @@ internal virtual void SetConfiguration(ConfigCanonicalName configCanonicalName)
// REVIEW/TODO: shall we abandon accessing automation here and just look at MSBuild state?
EnvDTE.Project automationObject = this.GetAutomationObject() as EnvDTE.Project;
ConfigCanonicalName currentConfigName;
if (Utilities.TryGetActiveConfigurationAndPlatform(this.Site, InteropSafeIVsHierarchy, out currentConfigName))
if (Utilities.TryGetActiveConfigurationAndPlatform(this.Site, this.ProjectIDGuid, out currentConfigName))
{
if (currentConfigName == configCanonicalName) return;
}
......@@ -4346,7 +4346,7 @@ internal virtual void OnHandleConfigurationRelatedGlobalProperties(object sender
}
ConfigCanonicalName configCanonicalName;
if (!Utilities.TryGetActiveConfigurationAndPlatform(this.Site, InteropSafeIVsHierarchy, out configCanonicalName))
if (!Utilities.TryGetActiveConfigurationAndPlatform(this.Site, this.ProjectIDGuid, out configCanonicalName))
{
throw new InvalidOperationException();
}
......
......@@ -940,20 +940,14 @@ public static string CanonicalizeFileNameNoThrow(string anyFileName)
/// <param name="configuration">The name of the active configuration.</param>
/// <param name="platform">The name of the platform.</param>
/// <returns>true if successfull.</returns>
/*internal, but public for FSharp.Project.dll*/ public static bool TryGetActiveConfigurationAndPlatform(System.IServiceProvider serviceProvider, IVsHierarchy hierarchy, out ConfigCanonicalName configCanonicalName)
/*internal, but public for FSharp.Project.dll*/ public static bool TryGetActiveConfigurationAndPlatform(System.IServiceProvider serviceProvider, Guid projectId, out ConfigCanonicalName configCanonicalName)
{
if (serviceProvider == null)
{
throw new ArgumentNullException("serviceProvider");
}
if (hierarchy == null)
{
throw new ArgumentNullException("hierarchy");
}
IVsSolutionBuildManager2 solutionBuildManager = serviceProvider.GetService(typeof(SVsSolutionBuildManager)) as IVsSolutionBuildManager2;
IVsSolutionBuildManager5 solutionBuildManager = serviceProvider.GetService(typeof(SVsSolutionBuildManager)) as IVsSolutionBuildManager5;
if (solutionBuildManager == null)
{
......@@ -961,17 +955,11 @@ public static string CanonicalizeFileNameNoThrow(string anyFileName)
return false;
}
IVsProjectCfg[] activeConfigs = new IVsProjectCfg[1];
ErrorHandler.ThrowOnFailure(solutionBuildManager.FindActiveProjectCfg(IntPtr.Zero, IntPtr.Zero, hierarchy, activeConfigs));
IVsProjectCfg activeCfg = activeConfigs[0];
// Can it be that the activeCfg is null?
System.Diagnostics.Debug.Assert(activeCfg != null, "Cannot find the active configuration");
string canonicalName;
ErrorHandler.ThrowOnFailure(activeCfg.get_CanonicalName(out canonicalName));
ErrorHandler.ThrowOnFailure(solutionBuildManager.FindActiveProjectCfgName(projectId, out canonicalName));
configCanonicalName = new ConfigCanonicalName(canonicalName);
return true;
}
......
......@@ -2137,7 +2137,7 @@ See also ...\SetupAuthoring\FSharp\Registry\FSProjSys_Registration.wxs, e.g.
if GetCaption(pHierProj) = GetCaption(projNode.InteropSafeIVsHierarchy) then
// This code matches what ProjectNode.SetConfiguration would do; that method cannot be called during a build, but at this
// current moment in time, it is 'safe' to do this update.
let _,currentConfigName = Utilities.TryGetActiveConfigurationAndPlatform(projNode.Site, projNode.InteropSafeIVsHierarchy)
let _,currentConfigName = Utilities.TryGetActiveConfigurationAndPlatform(projNode.Site, projNode.ProjectIDGuid)
MSBuildProject.SetGlobalProperty(projNode.BuildProject, ProjectFileConstants.Configuration, currentConfigName.ConfigName)
MSBuildProject.SetGlobalProperty(projNode.BuildProject, ProjectFileConstants.Platform, currentConfigName.MSBuildPlatform)
projNode.UpdateMSBuildState()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册