in vsintegration/src/FSharp.ProjectSystem.Base/Project/HierarchyNode.cs [3116:3209]
public int UpdateTargetFramework(
IVsHierarchy hier,
string currentTargetFrameworkMoniker,
string newTargetFrameworkMoniker
)
{
System.Runtime.Versioning.FrameworkName oldFrameworkName;
System.Runtime.Versioning.FrameworkName frameworkName = null;
try
{
oldFrameworkName = new System.Runtime.Versioning.FrameworkName(currentTargetFrameworkMoniker);
frameworkName = new System.Runtime.Versioning.FrameworkName(newTargetFrameworkMoniker);
}
catch (ArgumentException)
{
return VSConstants.E_INVALIDARG;
}
Debug.Assert(oldFrameworkName.Identifier == frameworkName.Identifier);
projectMgr.BuildProject.SetProperty(ProjectFileConstants.TargetFrameworkVersion, HierarchyNode.GetFrameworkVersionString(frameworkName));
projectMgr.BuildProject.SetProperty(ProjectFileConstants.TargetFrameworkProfile, frameworkName.Profile);
string targetFSharpCoreVersion = projectMgr.BuildProject.GetPropertyValue(ProjectFileConstants.TargetFSharpCoreVersion);
bool autoGenerateBindingRedirects;
bool.TryParse(projectMgr.BuildProject.GetPropertyValue("AutoGenerateBindingRedirects"), out autoGenerateBindingRedirects);
// In reality for FSharp.Core compatibility with .NetFramework selection looks like this:
// 2 is incompatible with 4
// 4.0 is incompatible with 4.5
// 4.5 is compatible with 4.5.1 and 4.5.2 and 4.6
var lower = oldFrameworkName.Version < frameworkName.Version ? oldFrameworkName.Version : frameworkName.Version;
var upper = oldFrameworkName.Version < frameworkName.Version ? frameworkName.Version : oldFrameworkName.Version;
var hasIncompatibleFsCore = (lower.Major != upper.Major) || (lower.Major == 4 && (lower.Minor < 5 && upper.Minor >= 5));
if (hasIncompatibleFsCore)
{
var newVersion =
frameworkName.Version.Major >= 4 ?
( frameworkName.Version.Minor < 5 ? new Version(4, 3, 0, 0) : new Version(4, 4, 0, 0) ) : new Version(2, 3, 0, 0);
targetFSharpCoreVersion = newVersion.ToString();
if (projectMgr.CanUseTargetFSharpCoreReference)
{
// this project controls version of FSharp.Core with project level property TargetFSharpCoreVersion- set it
projectMgr.SetProjectProperty(ProjectFileConstants.TargetFSharpCoreVersion, targetFSharpCoreVersion);
}
else
{
// project doesn't use TargetFSharpCoreVersion - fix the reference explicitly
var fsCoreName = new System.Reflection.AssemblyName(string.Format("FSharp.Core, Culture=neutral, PublicKeyToken={0}", Utilities.FsCorePublicKeyToken));
var vsProj = (VSLangProj.VSProject)projectMgr.Object;
var references = vsProj.References;
// replace existing fscore with one that has matching version with current target framework
var existingFsCore =
Microsoft.VisualStudio.FSharp.LanguageService.UIThread.DoOnUIThread(
() => references
.OfType<Automation.OAAssemblyReference>()
.FirstOrDefault(r => r.Name == fsCoreName.Name && r.PublicKeyToken == Utilities.FsCorePublicKeyToken && r.Culture == fsCoreName.CultureName)
);
if (existingFsCore != null)
{
Microsoft.VisualStudio.FSharp.LanguageService.UIThread.DoOnUIThread(() =>
{
// save copyLocal value - after calling existingFsCore.Remove() becomes invalid and can raise exceptions
var copyLocal = existingFsCore.CopyLocal;
existingFsCore.Remove();
fsCoreName.Version = newVersion;
// stores assembly FQN
var newRef = references.Add(fsCoreName.FullName);
newRef.CopyLocal = copyLocal;
});
}
}
}
try
{
this.projectMgr.FixupAppConfigOnTargetFXChange(newTargetFrameworkMoniker, targetFSharpCoreVersion, autoGenerateBindingRedirects);
}
catch(Exception e)
{
Debug.Assert(false, "Failed with e " + e.ToString());
return VSConstants.E_FAIL;
}
return VSConstants.S_OK;
}