diff options
author | Matt Ward <matt.ward@microsoft.com> | 2019-10-29 20:01:13 +0300 |
---|---|---|
committer | Matt Ward <ward.matt@gmail.com> | 2019-10-30 12:14:50 +0300 |
commit | b733a2859154b413cd506d9f0b054d15643c1fd2 (patch) | |
tree | c4f007887fa7cd835e75a810ba5d620b7be34f70 /main/src/addins/MonoDevelop.DotNetCore | |
parent | de3041d9a0ba211c7568ee2b1525d8dda2d91ebf (diff) |
[DotNetCore] Fix incorrect folders displayed for multi-target projects
If a multi-target project used .NET Standard 2.1, or .NET Core 3.0, and
an older framework such as .NET Standard 2.0, or .NET Core 2.1, then
the Solution window would not show the correct folders under the
Dependencies folder. If the first target framework was .NET Standard
2.0 then an SDK folder would be displayed for all frameworks. If the
first target framework was .NET Standard 2.1 then a Frameworks folder
would be displayed for all frameworks.
The problem was that there was no multi-target support for
FrameworkReferences. Each framework that supports FrameworkReferences
needs to have the ResolveFrameworkReferences MSBuild target called
separately. Also all project target frameworks are checked individually
when building the Solution window tree nodes. Previously the first
target framework was being considered when building the Frameworks
folder.
Fixes VSTS #1001442 - [Multitargeting] Incorrect Framework version
Diffstat (limited to 'main/src/addins/MonoDevelop.DotNetCore')
8 files changed, 212 insertions, 37 deletions
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNode.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNode.cs index 701c96ef07..80d230895c 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNode.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNode.cs @@ -119,10 +119,12 @@ namespace MonoDevelop.DotNetCore.NodeBuilders { bool addedFrameworkReferencesNode = false; if (frameworkNode != null) { - var frameworkReferencesNode = new FrameworkReferencesNode (this); - if (frameworkReferencesNode.HasChildNodes ()) { - addedFrameworkReferencesNode = true; - yield return frameworkReferencesNode; + if (frameworkNode.CanGetFrameworkReferences ()) { + var frameworkReferencesNode = new FrameworkReferencesNode (frameworkNode); + if (frameworkReferencesNode.HasChildNodes ()) { + addedFrameworkReferencesNode = true; + yield return frameworkReferencesNode; + } } var packagesNode = new PackageDependenciesNode (frameworkNode); @@ -135,10 +137,12 @@ namespace MonoDevelop.DotNetCore.NodeBuilders yield return sdkNode; } } else { - var frameworkReferencesNode = new FrameworkReferencesNode (this); - if (frameworkReferencesNode.HasChildNodes ()) { - addedFrameworkReferencesNode = true; - yield return frameworkReferencesNode; + if (FrameworkReferenceNodeCache.CanGetFrameworkReferences (Project)) { + var frameworkReferencesNode = new FrameworkReferencesNode (this); + if (frameworkReferencesNode.HasChildNodes ()) { + addedFrameworkReferencesNode = true; + yield return frameworkReferencesNode; + } } var packagesNode = new PackageDependenciesNode (this); diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/FrameworkReferenceNodeCache.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/FrameworkReferenceNodeCache.cs index 1fecf83e27..d5cc4ecdda 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/FrameworkReferenceNodeCache.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/FrameworkReferenceNodeCache.cs @@ -30,8 +30,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; using MonoDevelop.Ide; using MonoDevelop.Projects; +using NuGet.Frameworks; namespace MonoDevelop.DotNetCore.NodeBuilders { @@ -40,7 +42,8 @@ namespace MonoDevelop.DotNetCore.NodeBuilders static DotNetCoreVersion Version30 = DotNetCoreVersion.Parse ("3.0"); static DotNetCoreVersion Version21 = DotNetCoreVersion.Parse ("2.1"); - List<FrameworkReference> references = new List<FrameworkReference> (); + Dictionary<string, List<FrameworkReference>> referenceMappings = + new Dictionary<string, List<FrameworkReference>> (); CancellationTokenSource cancellationTokenSource; public FrameworkReferenceNodeCache (DotNetProject project) @@ -62,7 +65,7 @@ namespace MonoDevelop.DotNetCore.NodeBuilders public void Refresh () { try { - if (!CanGetFrameworkReferences ()) { + if (!CanGetFrameworkReferences (Project)) { LoadedReferences = true; return; } @@ -74,10 +77,20 @@ namespace MonoDevelop.DotNetCore.NodeBuilders } } - bool CanGetFrameworkReferences () + public static bool CanGetFrameworkReferences (DotNetProject project) { - return Project.TargetFramework.IsNetCoreAppOrHigher (Version30) || - Project.TargetFramework.IsNetStandardOrHigher (Version21); + foreach (TargetFrameworkMoniker targetFramework in project.TargetFrameworkMonikers) { + if (CanGetFrameworkReferences (targetFramework)) { + return true; + } + } + return false; + } + + public static bool CanGetFrameworkReferences (TargetFrameworkMoniker targetFramework) + { + return targetFramework.IsNetCoreAppOrHigher (Version30) || + targetFramework.IsNetStandardOrHigher (Version21); } void CancelCurrentRefresh () @@ -97,21 +110,29 @@ namespace MonoDevelop.DotNetCore.NodeBuilders .ContinueWith (task => OnFrameworkReferencesRead (task, tokenSource), TaskScheduler.FromCurrentSynchronizationContext ()); } - Task<List<FrameworkReference>> GetFrameworkReferencesAsync (CancellationTokenSource tokenSource) + Task<Dictionary<string, List<FrameworkReference>>> GetFrameworkReferencesAsync (CancellationTokenSource tokenSource) { - var configurationSelector = IdeApp.IsInitialized ? IdeApp.Workspace?.ActiveConfiguration ?? ConfigurationSelector.Default : ConfigurationSelector.Default; + var config = IdeApp.IsInitialized ? IdeApp.Workspace.ActiveConfiguration : ConfigurationSelector.Default; return Task.Run (async () => { - var references = await Project.GetFrameworkReferences (configurationSelector, tokenSource.Token) - .ConfigureAwait (false); + var referenceMappings = new Dictionary<string, List<FrameworkReference>> (); + foreach (TargetFrameworkMoniker framework in Project.TargetFrameworkMonikers) { + if (!CanGetFrameworkReferences (framework)) + continue; - if (!tokenSource.IsCancellationRequested) - return references.ToList (); + var frameworkConfig = new DotNetProjectFrameworkConfigurationSelector (config, framework.ShortName); + var references = await Project.GetFrameworkReferences (frameworkConfig, tokenSource.Token) + .ConfigureAwait (false); - return null; + if (!tokenSource.IsCancellationRequested) { + string key = GetMappingKey (framework); + referenceMappings [key] = references.ToList (); + } + } + return referenceMappings; }); } - void OnFrameworkReferencesRead (Task<List<FrameworkReference>> task, CancellationTokenSource tokenSource) + void OnFrameworkReferencesRead (Task<Dictionary<string, List<FrameworkReference>>> task, CancellationTokenSource tokenSource) { try { if (task.IsFaulted) { @@ -122,7 +143,7 @@ namespace MonoDevelop.DotNetCore.NodeBuilders LoggingService.LogError ("OnFrameworkReferencesRead error.", ex); } } else if (!tokenSource.IsCancellationRequested) { - references = task.Result; + referenceMappings = task.Result; LoadedReferences = true; OnFrameworkReferencesChanged (); } @@ -131,9 +152,25 @@ namespace MonoDevelop.DotNetCore.NodeBuilders } } - public IEnumerable<FrameworkReferenceNode> GetFrameworkReferenceNodes () + public IEnumerable<FrameworkReferenceNode> GetFrameworkReferenceNodes (TargetFrameworkMoniker framework) + { + string key = GetMappingKey (framework); + if (referenceMappings.TryGetValue (key, out List<FrameworkReference> references)) { + return references.Select (reference => new FrameworkReferenceNode (reference)); + } + return Enumerable.Empty<FrameworkReferenceNode> (); + } + + /// <summary> + /// Target framework versions returned from ResolvePackageDependenciesDesignTime use four part version numbers + /// so we cannot use TargetFrameworkMoniker as the dictionary key since this will not always match the + /// project's target framework. Instead generate a NuGetFramework and use that as the key since it will + /// normalize the version numbers. + /// </summary> + static string GetMappingKey (TargetFrameworkMoniker framework) { - return references.Select (reference => new FrameworkReferenceNode (reference)); + NuGetFramework nugetFramework = NuGetFramework.ParseFrameworkName (framework.ToString (), DefaultFrameworkNameProvider.Instance); + return nugetFramework.ToString (); } } } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/FrameworkReferencesNode.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/FrameworkReferencesNode.cs index 7dfa7e896b..b3cfab6b64 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/FrameworkReferencesNode.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/FrameworkReferencesNode.cs @@ -27,6 +27,7 @@ using System.Collections.Generic; using System.Linq; using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; using MonoDevelop.Ide.Gui; using MonoDevelop.Projects; @@ -41,10 +42,18 @@ namespace MonoDevelop.DotNetCore.NodeBuilders ParentNode = parentNode; } + public FrameworkReferencesNode (TargetFrameworkNode frameworkNode) + { + FrameworkNode = frameworkNode; + ParentNode = frameworkNode.DependenciesNode; + } + internal DotNetProject Project { get { return ParentNode.Project; } } + internal TargetFrameworkNode FrameworkNode { get; private set; } + internal DependenciesNode ParentNode { get; private set; } public string GetLabel () @@ -77,7 +86,7 @@ namespace MonoDevelop.DotNetCore.NodeBuilders public IEnumerable<FrameworkReferenceNode> GetChildNodes () { if (ParentNode.FrameworkReferencesCache.LoadedReferences) { - return ParentNode.FrameworkReferencesCache.GetFrameworkReferenceNodes (); + return ParentNode.FrameworkReferencesCache.GetFrameworkReferenceNodes (GetTargetFrameworkMoniker ()); } else { return GetDefaultNodes (); } @@ -88,9 +97,19 @@ namespace MonoDevelop.DotNetCore.NodeBuilders /// </summary> public IEnumerable<FrameworkReferenceNode> GetDefaultNodes () { - if (Project.TargetFramework.IsNetCoreApp ()) + return GetDefaultNodes (GetTargetFrameworkMoniker ()); + } + + TargetFrameworkMoniker GetTargetFrameworkMoniker () + { + return FrameworkNode?.GetTargetFrameworkMoniker () ?? Project.TargetFramework.Id; + } + + IEnumerable<FrameworkReferenceNode> GetDefaultNodes (TargetFrameworkMoniker targetFramework) + { + if (targetFramework.IsNetCoreApp ()) yield return new FrameworkReferenceNode ("Microsoft.NETCore.App"); - else if (Project.TargetFramework.IsNetStandard ()) + else if (targetFramework.IsNetStandard ()) yield return new FrameworkReferenceNode ("NETStandard.Library"); } } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/TargetFrameworkNode.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/TargetFrameworkNode.cs index 6710f8d0b2..37223abb41 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/TargetFrameworkNode.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/TargetFrameworkNode.cs @@ -24,8 +24,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +using System;
using System.Collections.Generic; using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; using MonoDevelop.Projects; namespace MonoDevelop.DotNetCore.NodeBuilders @@ -80,5 +82,15 @@ namespace MonoDevelop.DotNetCore.NodeBuilders { return DependenciesNode.GetChildNodes (this); } + + public bool CanGetFrameworkReferences () + { + return FrameworkReferenceNodeCache.CanGetFrameworkReferences (GetTargetFrameworkMoniker ()); + } + + internal TargetFrameworkMoniker GetTargetFrameworkMoniker () + { + return new TargetFrameworkMoniker (dependency.Name, dependency.Version); + } } } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DependencyNodeTests.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DependencyNodeTests.cs index 170d494608..654239aba0 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DependencyNodeTests.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DependencyNodeTests.cs @@ -51,6 +51,7 @@ namespace MonoDevelop.DotNetCore.Tests PackageDependenciesNode nugetFolderNode; FrameworkReferencesNode frameworksFolderNode; TaskCompletionSource<bool> packageDependenciesChanged; + TaskCompletionSource<bool> frameworkReferencesChanged; TestableDependenciesNodeBuilder dependenciesNodeBuilder; // Ensure NuGet.Versioning assembly is loaded by the tests otherwise they fail // when run from the command line with mdtool. @@ -79,7 +80,9 @@ namespace MonoDevelop.DotNetCore.Tests dependenciesNodeBuilder = new TestableDependenciesNodeBuilder (); dependenciesNode = new DependenciesNode (project, updatedNuGetPackages ?? PackageManagementServices.UpdatedPackagesInWorkspace); dependenciesNode.PackageDependencyCache.PackageDependenciesChanged += PackageDependenciesChanged; + dependenciesNode.FrameworkReferencesCache.FrameworkReferencesChanged += FrameworkReferencesChanged; packageDependenciesChanged = new TaskCompletionSource<bool> (); + frameworkReferencesChanged = new TaskCompletionSource<bool> (); dependenciesNode.PackageDependencyCache.Refresh (); dependenciesNode.FrameworkReferencesCache.Refresh (); @@ -97,6 +100,11 @@ namespace MonoDevelop.DotNetCore.Tests packageDependenciesChanged.TrySetResult (true); } + void FrameworkReferencesChanged (object sender, EventArgs e) + { + frameworkReferencesChanged.TrySetResult (true); + } + async Task WaitForPackageDependenciesChanged (int millisecondsTimeout = 60000) { var timeoutTask = Task.Delay (millisecondsTimeout); @@ -105,6 +113,14 @@ namespace MonoDevelop.DotNetCore.Tests Assert.Fail ("Timed out waiting for package dependencies to be updated."); } + async Task WaitForFrameworkReferencesChanged (int millisecondsTimeout = 60000) + { + var timeoutTask = Task.Delay (millisecondsTimeout); + var result = await Task.WhenAny (timeoutTask, frameworkReferencesChanged.Task); + if (result == timeoutTask) + Assert.Fail ("Timed out waiting for framework references to be updated."); + } + static SdkDependenciesNode GetSdkFolder (TargetFrameworkNode frameworkNode) { var nodeBuilder = new TestableTargetFrameworkNodeBuilder (); @@ -160,6 +176,13 @@ namespace MonoDevelop.DotNetCore.Tests return nodeBuilder.ChildNodesAsFrameworkReferenceNode ().ToList (); } + static FrameworkReferencesNode GetFrameworkReferencesFolder (TargetFrameworkNode node) + { + var nodeBuilder = new TestableTargetFrameworkNodeBuilder (); + nodeBuilder.BuildChildNodes (null, node); + return nodeBuilder.FrameworkReferences; + } + static bool IsDotNetCoreSdk30OrLaterInstalled () { return DotNetCoreSdk.Versions.Any (version => version.Major == 3); @@ -507,5 +530,72 @@ namespace MonoDevelop.DotNetCore.Tests // No updates label. Assert.AreEqual (string.Empty, frameworksFolderNode.GetSecondaryLabel ()); } + + [Test] + public async Task MultiTarget_NetStandard21_NetStandard20_NetCoreApp30_NetCoreApp21 () + { + if (!IsDotNetCoreSdk30OrLaterInstalled ()) { + Assert.Ignore (".NET Core 3 SDK is not installed."); + } + + FilePath projectFileName = Util.GetSampleProject ("DotNetCoreDependenciesFolder", "NetStandard21NetStandard20NetCore30NetCore21.csproj"); + Restore (projectFileName); + project = (DotNetProject)await Services.ProjectService.ReadSolutionItem (Util.GetMonitor (), projectFileName); + await CreateDependenciesNode (); + await WaitForFrameworkReferencesChanged (); + + var frameworkNodes = GetTargetFrameworkChildDependencies (); + var netstandard21FrameworkNode = frameworkNodes.Single (node => node.Name == ".NETStandard" && node.GetSecondaryLabel () == "(2.1.0.0)"); + var netstandard20FrameworkNode = frameworkNodes.Single (node => node.Name == ".NETStandard" && node.GetSecondaryLabel () == "(2.0.0.0)"); + var netCoreApp30FrameworkNode = frameworkNodes.Single (node => node.Name == ".NETCoreApp" && node.GetSecondaryLabel () == "(3.0.0.0)"); + var netCoreApp21FrameworkNode = frameworkNodes.Single (node => node.Name == ".NETCoreApp" && node.GetSecondaryLabel () == "(2.1.0.0)"); + + // .NET Standard 2.1 nodes + var frameworksFolder = GetFrameworkReferencesFolder (netstandard21FrameworkNode); + var frameworkNode = GetFrameworksFolderChildDependencies (frameworksFolder).Single (); + Assert.AreEqual ("NETStandard.Library", frameworkNode.Name); + Assert.AreEqual ("NETStandard.Library", frameworkNode.GetLabel ()); + Assert.IsTrue ( + frameworkNode.GetSecondaryLabel ().StartsWith ("(2.1."), + "Unexpected secondary label '{0}'", frameworkNode.GetSecondaryLabel ()); + + var defaultNode = frameworksFolder.GetDefaultNodes ().Single (); + Assert.AreEqual ("NETStandard.Library", defaultNode.Name); + Assert.AreEqual ("NETStandard.Library", defaultNode.GetLabel ()); + + // .NET Standard 2.0 nodes. + var sdkFolder = GetSdkFolder (netstandard20FrameworkNode); + var packageDependency = GetSdkFolderChildDependencies (sdkFolder).Single (); + Assert.AreEqual ("NETStandard.Library", packageDependency.Name); + Assert.AreEqual ("NETStandard.Library", packageDependency.GetLabel ()); + Assert.IsTrue ( + packageDependency.GetSecondaryLabel ().StartsWith ("(2.0."), + "Unexpected secondary label '{0}'", packageDependency.GetSecondaryLabel ()); + + // .NET Core 3.0 nodes. + frameworksFolder = GetFrameworkReferencesFolder (netCoreApp30FrameworkNode); + frameworkNode = GetFrameworksFolderChildDependencies (frameworksFolder).Single (); + Assert.AreEqual ("Microsoft.NETCore.App", frameworkNode.Name); + Assert.AreEqual ("Microsoft.NETCore.App", frameworkNode.GetLabel ()); + Assert.IsTrue ( + frameworkNode.GetSecondaryLabel ().StartsWith ("(3.0."), + "Unexpected secondary label '{0}'", frameworkNode.GetSecondaryLabel ()); + + defaultNode = frameworksFolder.GetDefaultNodes ().Single (); + Assert.AreEqual ("Microsoft.NETCore.App", defaultNode.Name); + Assert.AreEqual ("Microsoft.NETCore.App", defaultNode.GetLabel ()); + + // .NET Core 2.1 nodes. + // Note that for some reason in a multi-target project a .NET Core 2.1 project also gets + // a .NET Standard dependency if .net standard is one of the frameworks. With a non-multi-target + // project this does not happen. + sdkFolder = GetSdkFolder (netCoreApp21FrameworkNode); + var packageDependencies = GetSdkFolderChildDependencies (sdkFolder); + packageDependency = packageDependencies.Single (p => p.Name == "Microsoft.NETCore.App"); + Assert.AreEqual ("Microsoft.NETCore.App", packageDependency.GetLabel ()); + Assert.IsTrue ( + packageDependency.GetSecondaryLabel ().StartsWith ("(2.1."), + "Unexpected secondary label '{0}'", packageDependency.GetSecondaryLabel ()); + } } } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/TestableTargetFrameworkNodeBuilder.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/TestableTargetFrameworkNodeBuilder.cs index f5ce8c4fbc..4f419c5c0a 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/TestableTargetFrameworkNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/TestableTargetFrameworkNodeBuilder.cs @@ -39,6 +39,7 @@ namespace MonoDevelop.DotNetCore.Tests public SdkDependenciesNode SdkDependencies; public ProjectDependenciesNode ProjectDependencies; public AssemblyDependenciesNode AssemblyDependencies; + public FrameworkReferencesNode FrameworkReferences; void AddChild (ITreeBuilder treeBuilder, object dataObject) { @@ -52,6 +53,8 @@ namespace MonoDevelop.DotNetCore.Tests ProjectDependencies = projectDependencies; } else if (dataObject is SdkDependenciesNode sdkDependencies) { SdkDependencies = sdkDependencies; + } else if (dataObject is FrameworkReferencesNode frameworkReferences) { + FrameworkReferences = frameworkReferences; } } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkExtensions.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkExtensions.cs index abe00243fa..b647a31ca6 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkExtensions.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkExtensions.cs @@ -82,20 +82,12 @@ namespace MonoDevelop.DotNetCore public static bool IsNetCoreAppOrHigher (this TargetFramework framework, DotNetCoreVersion version) { - DotNetCoreVersion.TryParse (framework.Id.Version, out var dotNetCoreVersion); - if (dotNetCoreVersion == null) - return false; - - return framework.Id.IsNetCoreApp () && dotNetCoreVersion >= version; + return framework.Id.IsNetCoreAppOrHigher (version); } public static bool IsNetStandardOrHigher (this TargetFramework framework, DotNetCoreVersion version) { - DotNetCoreVersion.TryParse (framework.Id.Version, out var dotNetCoreVersion); - if (dotNetCoreVersion == null) - return false; - - return framework.Id.IsNetStandard () && dotNetCoreVersion >= version; + return framework.Id.IsNetStandardOrHigher (version); } public static bool IsNetFramework (this TargetFramework framework) => framework.Id.IsNetFramework (); diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs index 4e25698a1d..0e52b80399 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/TargetFrameworkMonikerExtensions.cs @@ -49,5 +49,23 @@ namespace MonoDevelop.DotNetCore { return framework.IsNetStandard () || framework.IsNetCoreApp (); } + + public static bool IsNetCoreAppOrHigher (this TargetFrameworkMoniker framework, DotNetCoreVersion version) + { + DotNetCoreVersion.TryParse (framework.Version, out var dotNetCoreVersion); + if (dotNetCoreVersion == null) + return false; + + return framework.IsNetCoreApp () && dotNetCoreVersion >= version; + } + + public static bool IsNetStandardOrHigher (this TargetFrameworkMoniker framework, DotNetCoreVersion version) + { + DotNetCoreVersion.TryParse (framework.Version, out var dotNetCoreVersion); + if (dotNetCoreVersion == null) + return false; + + return framework.IsNetStandard () && dotNetCoreVersion >= version; + } } } |