Skip to content

Commit

Permalink
feat: add props reference support (-t props)
Browse files Browse the repository at this point in the history
  • Loading branch information
nevse committed Mar 26, 2024
1 parent 8dd214e commit 8a77f78
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 20 deletions.
1 change: 1 addition & 0 deletions ConvA/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace ConvA;

public class Config {
public string? RepositoryPath { get; set; }
public string? PropsPath { get; set; } = Path.Combine("xamarin", "Maui", "References");// relative to repository
public ConversionType? ConversionType { get; set; }
}

Expand Down
1 change: 0 additions & 1 deletion ConvA/Converters/PackageReferenceConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ public PackageReferenceConverter(RepoInfo repoInfo, string version) : base(repoI
private string Version { get; }

protected override void ConvertCore(Project project, HashSet<PackageInfo> packages, List<string> externPackages, List<string> assets, List<Reference> references, List<ProjectReference> projectReferences) {

foreach (PackageInfo package in packages) {
if (package.Id != null) {
project.AddOrUpdatePackageReference(package.Id, Version);
Expand Down
2 changes: 1 addition & 1 deletion ConvA/Converters/ProjectConverterBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ protected ProjectConverterBase(RepoInfo repoInfo) {

protected RepoInfo RepoInfo { get; }

public void Convert(Project project) {
public void Convert(Project project) {
var packageReferences = project.GetPackageReferences().Where(x => x.Name != null && RepoInfo.CanConvertPackage(x.Name)).ToList();
HashSet<PackageInfo> packages = new();
foreach (var packageReference in packageReferences) {
Expand Down
9 changes: 3 additions & 6 deletions ConvA/Converters/ProjectReferenceConverter.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
namespace ConvA;

public class ProjectReferenceConverter : ProjectConverterBase {
public ProjectReferenceConverter(RepoInfo repoInfo, bool useRefsForProjectReferences) : base(repoInfo) {
UseRefsForProjectReferences = useRefsForProjectReferences;
}

bool UseRefsForProjectReferences { get;}
public class ProjectReferenceConverter(RepoInfo repoInfo, bool useRefsForProjectReferences)
: ProjectConverterBase(repoInfo) {
bool UseRefsForProjectReferences { get;} = useRefsForProjectReferences;

protected override void ConvertCore(Project project, HashSet<PackageInfo> packages, List<string> externPackages, List<string> assets, List<Reference> references, List<ProjectReference> projectReferences) {
Dictionary<string, string> androidReferences = new();
Expand Down
43 changes: 43 additions & 0 deletions ConvA/Converters/PropsConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace ConvA;

public class PropsConverter(RepoInfo repoInfo) : ProjectConverterBase(repoInfo) {
protected override void ConvertCore(Project project, HashSet<PackageInfo> packages, List<string> externPackages, List<string> assets, List<Reference> references,
List<ProjectReference> projectReferences) {
//
// * remove old props (move code for detecting props in RepoInfo.GetPropsImports)
// * read from props all imported packages add dlls and maybe project references
//

foreach(string externPackage in externPackages) {
project.RemovePackage(externPackage);
}
foreach(PackageInfo package in packages) {
project.RemovePackage(package.Id!);
}
project.RemoveProjectReferences(projectReferences);
project.RemoveDllReferences(references);
foreach (var asset in assets) {
project.RemoveAsset(asset);
}

HashSet<string> props = new();
foreach (PackageInfo package in packages) {
foreach (var prop in RepoInfo.GetPropsImports(package.Id!)) {
props.Add(prop);
}
}
project.AddImports(props);
HashSet<string> packagesFromProps = new();
foreach (string propsFile in props) {
var propsProject = new Project(propsFile);
foreach (var package in propsProject.GetPackageReferences()) {
if (package.Name != null) {
packagesFromProps.Add(package.Name);
}
}
}

project.RemovePackages(packagesFromProps, reportMissed: false);
project.AddJsonProjectReference("m");//TODO: after detect dependencies
}
}
1 change: 1 addition & 0 deletions ConvA/Models/ConversionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ public enum ConversionType: int {
Proj2,
Package,
Dll,
Props
}
3 changes: 2 additions & 1 deletion ConvA/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,15 @@ static async Task<int> Run(string? repositoryPath, ConversionType? type, string?

repositoryPath = PathHelper.ExpandPath(repositoryPath);
string projectDir = File.Exists(actualProjectPath) ? Path.GetDirectoryName(actualProjectPath)! : actualProjectPath;
RepoInfo repoInfo = new(repositoryPath);
RepoInfo repoInfo = new(repositoryPath, config?.PropsPath ?? "xamarin/Maui/References");
repoInfo.Build();
string actualVersion = String.IsNullOrEmpty(packageVersion) ? repoInfo.GetVersion() : packageVersion;
ProjectConverterBase converter = type switch {
ConversionType.Proj => new ProjectReferenceConverter(repoInfo, false),
ConversionType.Proj2 => new ProjectReferenceConverter(repoInfo, true),
ConversionType.Dll => new DllReferenceConverter(repoInfo),
ConversionType.Package => new PackageReferenceConverter(repoInfo, actualVersion),
ConversionType.Props => new PropsConverter(repoInfo),
_ => throw new NotSupportedException($"Conversion type {type} is not supported")
};
IEnumerable<string> projectFiles = File.Exists(actualProjectPath) ? new[] { actualProjectPath } : Directory.EnumerateFiles(actualProjectPath, "*.csproj");
Expand Down
24 changes: 19 additions & 5 deletions ConvA/RepoInfo.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
using System.Text.RegularExpressions;
using System;
using System.ComponentModel;

namespace ConvA;

public partial class RepoInfo {
public partial class RepoInfo(string path, string propsPath) {
const string ProjectsBasePath = "xamarin/maui";
const string NuspecBasePath = "nuspec";


[GeneratedRegex(@"(\d+\.\d+\.\d+)-.*")]
private static partial Regex VersionRegex();

public RepoInfo(string path) {
BasePath = path;
}
string BasePath { get; } = path;

string PropsPath { get; } = propsPath;

string BasePath { get; }
//name, path
public Dictionary<string, string> ProjectsByNameDictionary { get; } = new();
public Dictionary<string, PackageInfo> PackagesByNameDictionary { get; } = new();
public string? DevExpressDataVersion { get; set; }
Expand Down Expand Up @@ -62,6 +63,19 @@ public Dictionary<string, string> GetIosReferences(string packageName) {
return package.ReferencesIos;
}

public List<string> GetPropsImports(string packageName) {
List<string> defaultImports = ["DevExpress.Build.props", "DevExpress.Common.props"];
List<string> propsImports = [];
string basePropsPath = Path.Combine(BasePath, PropsPath);
foreach (string import in defaultImports) {
string propsPath = Path.Combine(basePropsPath, import);
propsImports.Add(propsPath);
}
string packagePropsPath = Path.Combine(basePropsPath, $"{packageName}.props");
propsImports.Add(packagePropsPath);
return propsImports;
}

public IEnumerable<string> CalculateDependencies(string packageReferenceName, HashSet<string>? visited = null) {
visited ??= new HashSet<string>();
if (!PackagesByNameDictionary.TryGetValue(packageReferenceName, out PackageInfo? package))
Expand Down
90 changes: 84 additions & 6 deletions ConvA/Workspace/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,40 @@ public bool CheckCondition(XmlElement? element, string? condition) {
return conditionAttr.Replace(" ", "") == condition?.Replace(" ", "");
}

public void AddImports(IEnumerable<string> props) {
//add imports to the end of the file in project section
XmlNodeList? nodes = Document.SelectNodes("//Import");
if (nodes == null || nodes.Count <= 0) {
XmlNodeList? projectNodes = Document.SelectNodes("//Project");
if (projectNodes == null)
throw new EvaluateException("Could not find project node");
var projectNode = projectNodes[0];
foreach (string prop in props) {
XmlElement importNode = Document.CreateElement("Import");
importNode.SetAttribute("Project", prop);
projectNode?.AppendChild(importNode);
Console.WriteLine($"Add import {prop}");
}
} else {
foreach (string prop in props) {
bool isExist = false;
foreach (XmlNode node in nodes) {
string? include = node.Attributes?["Project"]?.Value;
if (String.Equals(include, prop, StringComparison.InvariantCultureIgnoreCase)) {
isExist = true;
break;
}
}
if (!isExist) {
XmlElement importNode = Document.CreateElement("Import");
importNode.SetAttribute("Project", prop);
nodes[0]?.ParentNode?.InsertAfter(importNode, nodes[nodes.Count - 1]);
Console.WriteLine($"Add import {prop}");
}
}
}

}
public void AddProjectReference(IEnumerable<string> references, string? platform = "", string? repoPath = null) {
IEnumerable<XmlNode> packageRefNodes = GetItemGroupWithPackageReference();
string? condition = null;
Expand Down Expand Up @@ -330,10 +364,7 @@ public void AddDllReference(Dictionary<string, string> references, string? platf
}

if (itemGroupNode == null) {
XmlNodeList? projectNodes = Document.SelectNodes("//Project");
if (projectNodes == null)
throw new EvaluateException("Could not find project node");
var projectNode = projectNodes[0];
XmlNode? projectNode = FindProjectNode();
projectNode?.AppendChild(refContentNode);
} else {
itemGroupNode.InsertAfter(refContentNode, packageRefNodes.Last());
Expand All @@ -355,7 +386,23 @@ public void AddDllReference(Dictionary<string, string> references, string? platf
}
}

public bool RemovePackage(string packageName) {
private XmlNode? FindProjectNode()
{
XmlNodeList? projectNodes = Document.SelectNodes("//Project");
if (projectNodes == null)
throw new EvaluateException("Could not find project node");
var projectNode = projectNodes[0];
return projectNode;
}

public bool RemovePackages(IEnumerable<string> packageName, bool reportMissed = true) {
bool isRemoved = false;
foreach (string package in packageName) {
isRemoved |= RemovePackage(package, reportMissed);
}
return isRemoved;
}
public bool RemovePackage(string packageName, bool reportMissed = true) {
XmlNodeList? packages = Document.SelectNodes("//ItemGroup/PackageReference");
bool isRemoved = false;
if (packages == null)
Expand All @@ -368,7 +415,10 @@ public bool RemovePackage(string packageName) {
node.ParentNode?.RemoveChild(node);
isRemoved = true;
}
Console.WriteLine($"Remove package {packageName}");
if (!isRemoved && !reportMissed)
return isRemoved;
string status = isRemoved ? "removed" : "missed";
Console.WriteLine($"Package {status} {packageName}");
return isRemoved;
}

Expand Down Expand Up @@ -691,6 +741,34 @@ public List<ProjectReference> GetProjectReferences() {
return references;
}

public void AddJsonProjectReference(string s) {
XmlNodeList? nodes = Document.SelectNodes("//ItemGroup");
if (nodes != null) {
foreach (XmlNode node in nodes) {
foreach (XmlNode subNode in node.ChildNodes) {
if (String.Equals("DXJsonProjectReference", subNode.Name, StringComparison.InvariantCultureIgnoreCase)) {
string? include = subNode.Attributes?["Include"]?.Value;
if (include == null)
continue;
if (include.Contains(s))
return;
}
}
}
}
XmlNode itemGroup = Document.CreateElement("ItemGroup");
if (nodes == null || nodes.Count == 0) {
var projectNode = FindProjectNode();
projectNode?.AppendChild(itemGroup);
} else {
var lastNode = nodes[^1];
lastNode?.ParentNode?.InsertAfter(itemGroup, lastNode);
}
XmlElement projectReference = Document.CreateElement("DXJsonProjectReference");
projectReference.SetAttribute("Include", s);
itemGroup.AppendChild(projectReference);
}

[GeneratedRegex(@"<!--.*?-->", RegexOptions.Singleline)]
private static partial Regex SignleLineCommentRegex();

Expand Down

0 comments on commit 8a77f78

Please sign in to comment.