using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml.Linq; using NUnit.Framework; using ProjectConverter.Platforms; // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. // For details see: http://anxframework.codeplex.com/license namespace ProjectConverter { public abstract class Converter { protected const string XnaGameStudioTarget = "Microsoft.Xna.GameStudio.targets"; protected const string XnaPipelineExtensionTarget = "Microsoft.Xna.GameStudio.ContentPipelineExtensions.targets"; protected ProjectPath CurrentProject { get; private set; } /// /// The Postfix is used as a extension for a project file name /// public abstract string Postfix { get; } /// /// The Name is used to identify the converter /// public abstract string Name { get; } /// /// When set to false the source project file will not be written to disk after conversion /// public virtual bool WriteSourceProjectToDestination { get { return true; } } /// /// Nex extension to use for the target file /// public virtual string TargetFileExtension { get { return string.Empty; } } public virtual string ProjectFileTemplate { get { return string.Empty; } } #region ConvertAllProjects public void ConvertAllProjects(string solutionFilepath, string destinationPath) { ProjectPath[] allProjects = CollectAllProjects(solutionFilepath, destinationPath); for (int index = 0; index < allProjects.Length; index++) { ConvertProject(allProjects[index]); } CreateTargetSolution(solutionFilepath, allProjects); } #endregion #region ConvertAnxContentProject public void ConvertAnxContentProject(string projectFilePath, string destinationPath) { ProjectPath projectPath = new ProjectPath(this, projectFilePath, ".", destinationPath, TargetFileExtension, ProjectFileTemplate); ConvertProject(projectPath); } #endregion #region ConvertProject public void ConvertProject(string projectFilePath, string destinationPath) { ProjectPath projectPath = new ProjectPath(this, projectFilePath, ".", destinationPath, TargetFileExtension); ConvertProject(projectPath); } public void ConvertProject(ProjectPath project) { CurrentProject = project; PreConvert(); string namespaceName = project.Root.Name.NamespaceName; XName importName = XName.Get("Import", namespaceName); XName rootNamespaceName = XName.Get("RootNamespace", namespaceName); XName propertyGroupName = XName.Get("PropertyGroup", namespaceName); XName itemGroupName = XName.Get("ItemGroup", namespaceName); XName definesName = XName.Get("DefineConstants", namespaceName); XName referenceName = XName.Get("Reference", namespaceName); XName projectReferenceName = XName.Get("ProjectReference", namespaceName); XName outputPathName = XName.Get("OutputPath", namespaceName); var groups = project.Root.Elements().ToList(); ConvertProject(project.Root); foreach (var group in groups) { if (group.Name == propertyGroupName) { XElement definesNode = group.Element(definesName); if (definesNode != null) { definesNode.Value = DefinesConverter.ConvertDefines(definesNode.Value, Postfix); } XElement outputPathNode = group.Element(outputPathName); if (outputPathNode != null) { outputPathNode.Value = ConvertOutputPath(outputPathNode.Value); } if (group.Element(rootNamespaceName) != null) { ConvertMainPropertyGroup(group); } else { ConvertPropertyGroup(group); } } else if (group.Name == importName) { XAttribute projectAttribute = group.Attribute("Project"); ConvertImport(group, projectAttribute); } else if (group.Name == itemGroupName) { var allReferences = group.Elements(referenceName).ToList(); foreach (var reference in allReferences) ConvertReference(reference); var allProjectReferences = group.Elements(projectReferenceName).ToList(); foreach (var projectReference in allProjectReferences) { FixProjectReferencePath(projectReference); ConvertProjectReference(projectReference); } ConvertItemGroup(group); } } PostConvert(); if (WriteSourceProjectToDestination) project.Save(); } #endregion #region ConvertMainPropertyGroup protected virtual void ConvertMainPropertyGroup(XElement element) { } #endregion #region ConvertPropertyGroup protected virtual void ConvertPropertyGroup(XElement element) { } #endregion #region ConvertItemGroup protected virtual void ConvertItemGroup(XElement element) { } #endregion #region ConvertProjectReference protected virtual void ConvertProjectReference(XElement element) { } #endregion #region ConvertReference protected virtual void ConvertReference(XElement element) { } #endregion #region ConvertProject protected virtual void ConvertProject(XElement element) { } #endregion #region ConvertImport protected virtual void ConvertImport(XElement element, XAttribute projectAttribute) { } #endregion #region ConvertOutputPath protected virtual string ConvertOutputPath(string path) { return path; } #endregion #region PreConvert protected virtual void PreConvert() { } #endregion #region PostConvert protected virtual void PostConvert() { } #endregion #region DeleteNodeIfExists protected void DeleteNodeIfExists(XElement group, string nodeName) { XName name = XName.Get(nodeName, group.Name.NamespaceName); XElement element = group.Element(name); if (element != null) { element.Remove(); } } #endregion #region GetXName protected XName GetXName(string nodeName) { return XName.Get(nodeName, CurrentProject.Document.Root.Name.NamespaceName); } #endregion #region GetOrCreateNode protected XElement GetOrCreateNode(XElement group, string nodeName) { XName name = XName.Get(nodeName, group.Name.NamespaceName); XElement element = group.Element(name); if (element == null) { element = new XElement(name); group.Add(element); } return element; } #endregion #region ChangeOrCreateNodeValue protected void ChangeOrCreateNodeValue(XElement group, string nodeName, string value) { GetOrCreateNode(group, nodeName).Value = value; } #endregion #region FixProjectReferencePath private void FixProjectReferencePath(XElement projectReference) { XAttribute includeAttribute = projectReference.Attribute("Include"); if (includeAttribute != null) { string referencePath = includeAttribute.Value; if (referencePath.EndsWith(".csproj")) { if (!string.IsNullOrEmpty(Postfix)) { referencePath = referencePath.Replace(".csproj", "_" + Postfix + ".csproj"); } string basePath = Path.GetDirectoryName(CurrentProject.FullSourcePath); string fullReferencePath = Path.Combine(basePath, referencePath); if (File.Exists(fullReferencePath)) { includeAttribute.Value = referencePath; } } } } #endregion #region CollectAllProjects private ProjectPath[] CollectAllProjects(string solutionFilepath, string destinationPath) { var solution = VsSolution.Load(solutionFilepath); var result = new List(); string basePath = Path.GetDirectoryName(solutionFilepath); foreach (var project in solution.Projects) if (project.IsCsProject && project.RelativePath.Contains("Tools") == false) result.Add(new ProjectPath(this, project.RelativePath, basePath, destinationPath, string.Empty)); return result.ToArray(); } #endregion #region CreateTargetSolution private void CreateTargetSolution(string solutionFilepath, ProjectPath[] allProjects) { string[] allLines = File.ReadAllLines(solutionFilepath); for (int index = 0; index < allLines.Length; index++) { foreach (var project in allProjects) { string replaceText = "\"" + project.RelativeSourcePath + "\""; if (allLines[index].Contains(replaceText)) { allLines[index] = allLines[index].Replace(replaceText, "\"" + project.RelativeDestinationPath + "\""); } } } string targetSolutionPath = solutionFilepath.Substring(0, solutionFilepath.Length - ".sln".Length); targetSolutionPath += "_" + Postfix + ".sln"; File.WriteAllLines(targetSolutionPath, allLines); } #endregion private class ConverterTests { #region TestCollectAllProjects [Test] public static void TestCollectAllProjects() { const string filepath = @"D:\code\csharp\ANX.Framework\ANX.Framework.sln"; var converter = new MetroConverter(); ProjectPath[] result = converter.CollectAllProjects(filepath, string.Empty); Assert.Greater(result.Length, 0); } #endregion #region TestConvertSolutionMetro [Test] public static void TestConvertSolutionMetro() { const string filepath = @"D:\code\csharp\ANX.Framework\ANX.Framework.sln"; var converter = new MetroConverter(); converter.ConvertAllProjects(filepath, string.Empty); } #endregion #region TestConvertSolutionPsVita [Test] public static void TestConvertSolutionPsVita() { const string filepath = @"D:\code\csharp\ANX.Framework\ANX.Framework.sln"; var converter = new PsVitaConverter(); converter.ConvertAllProjects(filepath, string.Empty); } #endregion #region TestConvertSolutionLinux [Test] public static void TestConvertSolutionLinux() { const string filepath = @"D:\code\csharp\ANX.Framework\ANX.Framework.sln"; var converter = new LinuxConverter(); converter.ConvertAllProjects(filepath, string.Empty); } #endregion } } }