// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project.Converter;
using ICSharpCode.SharpDevelop.Project.TargetFrameworks;
namespace ICSharpCode.SharpDevelop.Project
{
public abstract class TargetFramework
{
public static readonly TargetFramework Net20 = new DotNet20();
public static readonly TargetFramework Net30 = new DotNet30();
public static readonly TargetFramework Net35 = new DotNet35();
public static readonly TargetFramework Net35Client = new DotNet35Client();
public static readonly TargetFramework Net40 = new DotNet4x(Versions.V4_0, RedistLists.Net40, DotnetDetection.IsDotnet40Installed);
public static readonly TargetFramework Net40Client = new DotNet4xClient(Versions.V4_0, RedistLists.Net40Client, DotnetDetection.IsDotnet40Installed);
public static readonly TargetFramework Net45 = new DotNet4x(Versions.V4_5, RedistLists.Net45, DotnetDetection.IsDotnet45Installed);
public static readonly TargetFramework Net451 = new DotNet4x(Versions.V4_5_1, RedistLists.Net45, DotnetDetection.IsDotnet451Installed);
public static readonly TargetFramework Net452 = new DotNet4x(Versions.V4_5_2, RedistLists.Net45, DotnetDetection.IsDotnet452Installed);
public static readonly TargetFramework Net46 = new DotNet4x(Versions.V4_6, RedistLists.Net46, DotnetDetection.IsDotnet46Installed);
///
/// Retrieves a target framework by a 'name'.
/// Used by the .xpt project system; please do not use anywhere else.
///
internal static TargetFramework GetByName(string name)
{
foreach (var fx in SD.ProjectService.TargetFrameworks) {
// Yes, put version + profile together without any separator... that's how we indicated the Client profiles in SD 4.x and the .xpt file format
if (fx.TargetFrameworkVersion + fx.TargetFrameworkProfile == name)
return fx;
}
return null;
}
internal const string DefaultTargetFrameworkVersion = "v4.0";
internal const string DefaultTargetFrameworkProfile = "";
///
/// Gets the name of the target framework.
/// This is used in the project's <TargetFrameworkVersion> element.
///
public abstract string TargetFrameworkVersion { get; }
///
/// Gets the profile of the target framework.
/// This is used in the project's <TargetFrameworkProfile> element.
///
/// Returns the empty string if no profile name is in use.
///
public virtual string TargetFrameworkProfile {
get { return string.Empty; }
}
///
/// Gets the corresponding .NET desktop framework version.
/// If this target framework is not a .NET desktop version, gets the closest corresponding version.
///
public abstract Version Version { get; }
///
/// Gets the display name of the target framework.
///
public virtual string DisplayName {
get { return this.TargetFrameworkVersion; }
}
///
/// Gets the minimum MSBuild version required to build projects with this target framework.
///
public abstract Version MinimumMSBuildVersion { get; }
///
/// Gets whether this is the MS.NET Framework for the desktop. (not Mono, not WinPhone/Win8 app/portable library/...)
///
public virtual bool IsDesktopFramework {
get { return false; }
}
public virtual bool Supports32BitPreferredOption {
get { return Version >= Versions.V4_5; }
}
///
/// Supported runtime version string for app.config
///
public virtual string SupportedRuntimeVersion {
get { return null; }
}
///
/// Supported SKU string for app.config.
///
public virtual string SupportedSku {
get { return null; }
}
///
/// Specifies whether this target framework requires an explicit app.config entry.
///
public virtual bool RequiresAppConfigEntry {
get { return false; }
}
///
/// Gets whether this target framework in an "improved version" of the specified framework.
/// This should usually return whether this framework is (mostly) backward-compatible with the specified framework.
///
/// The 'IsBasedOn' relation should be reflexive and transitive.
public virtual bool IsBasedOn(TargetFramework fx)
{
return fx == this;
}
///
/// Gets whether the runtime for the specified target framework is available on this machine.
/// This method controls whether the target framework is visible to the user.
///
/// Note: for the desktop frameworks, this method tests for run-time availability; it does not check if the reference assemblies are present.
///
public virtual bool IsAvailable()
{
return true;
}
///
/// Gets the solution format version corresponding to the older version of Visual Studio that supports this target framework.
///
/// The default implementation of this property is based on the property.
public virtual SolutionFormatVersion MinimumSolutionVersion {
get {
if (MinimumMSBuildVersion <= Versions.V2_0)
return SolutionFormatVersion.VS2005;
else if (MinimumMSBuildVersion <= Versions.V3_5)
return SolutionFormatVersion.VS2008;
else
return SolutionFormatVersion.VS2010;
}
}
/* We might implement+use this API in the future if we want to notify the user about missing reference assemblies.
///
/// Tests whether the reference assemblies for this framework are installed on this machine.
///
public virtual bool ReferenceAssembliesAvailable()
{
return true;
}
///
/// Returns the URL where the reference assemblies can be download.
/// May return null if the download location is unknown.
///
public virtual Uri ReferenceAssemblyDownloadLocation {
get { return null; }
}
///
/// Returns the name of the product that contains the reference assemblies for this framework. (for example: "Windows SDK x.y")
/// May return null if the source for the reference assemblies is unknown.
///
public virtual string ReferenceAssemblyDownloadVehicle {
get { return null; }
}
*/
///
/// Retrieves the list of reference assemblies for this framework.
/// May return an empty list if the reference assemblies are not installed.
///
public virtual IReadOnlyList ReferenceAssemblies {
get {
return EmptyList.Instance;
}
}
///
/// Reads the 'RedistList/FrameworkList.xml' file with the specified file name.
///
public static IReadOnlyList ReadRedistList(string redistListFileName)
{
List list = new List();
XDocument doc = XDocument.Load(redistListFileName);
foreach (var file in doc.Root.Elements()) {
string assemblyName = (string)file.Attribute("AssemblyName");
string version = (string)file.Attribute("Version");
string publicKeyToken = (string)file.Attribute("PublicKeyToken");
string culture = (string)file.Attribute("Culture");
//string processorArchitecture = (string)file.Attribute("ProcessorArchitecture");
if ((string)file.Attribute("InGAC") == "false" || (string)file.Attribute("InGac") == "false") {
// Ignore assemblies not in GAC.
// Note that casing of 'InGAC'/'InGac' is inconsistent between different .NET versions
continue;
}
list.Add(new DomAssemblyName(assemblyName, Version.Parse(version), publicKeyToken, culture));
}
return list;
}
///
/// Shows a dialog to pick the target framework.
/// This method is called by the UpgradeView 'convert' button to retrieve the actual target framework
///
public virtual TargetFramework PickFramework(IEnumerable selectedProjects)
{
return this;
}
public override string ToString()
{
return DisplayName;
}
}
}