using System; using System.IO; namespace InstallSources { /// /// Path manipulator that can deal with the Xamarin sources. /// public class XamarinSourcesPathMangler : IPathMangler { static string GeneratedExtension = ".g.cs"; static string NativeTypeSubpath = "NativeTypes"; static string CommonSourceSubpath = "/build/common/"; static string RuntimeSubpath = "generated.cs"; /// /// Gets and sets the path to the xamarin source. /// /// The xamarin source path. public string XamarinSourcePath { get; set; } /// /// Gets and sets the path used as the dir name for the framework. /// /// The framework path. public string FrameworkPath { get; set; } /// /// Gets or sets the install dir. /// /// The install dir. public string InstallDir { get; set; } /// /// Gets or sets the frame work dir. /// /// The frame work dir. public string DestinationDir { get; set; } /// /// Returns if the provided path was compiler generated or not. /// /// true, if generated path was generated, false otherwise. /// The source path to mangle. static bool IsGeneratedPath (string path) { return path.EndsWith (GeneratedExtension, StringComparison.InvariantCulture); } /// /// Returns if the source file is part of the common source generated by the generator. /// /// true, if common source was ised, false otherwise. /// Path. public static bool IsManualSource (string path) { return path.EndsWith (".cs", StringComparison.CurrentCulture) && !path.Contains (CommonSourceSubpath) && !path.Contains (NativeTypeSubpath); } /// /// Returns if the provided path is a NativeType. /// /// true, if native type was ised, false otherwise. /// Path. static bool IsNativeType (string path) { return path.Contains (NativeTypeSubpath); } /// /// Returns if the pat is from the runtime generated code. /// /// true, if runrime was ised, false otherwise. /// Path. static bool IsRunrime (string path) { return path.Contains (RuntimeSubpath); } /// /// Returns the source path for a generated file. /// /// The source path for native type. /// Path. string GetSourcePathForGeneratedPath (string path) => path; /// /// Returns the source path for the native common types. /// /// The source path for native type. /// Path. string GetSourcePathForNativeType (string path) { string src = ""; var pos = path.IndexOf (CommonSourceSubpath, StringComparison.InvariantCulture); if (pos >= 0) { src = path.Remove (0, pos + CommonSourceSubpath.Length); src = Path.Combine (XamarinSourcePath, "build", "common", src); } else { pos = path.IndexOf (NativeTypeSubpath, StringComparison.InvariantCulture); if (pos >= 0) { src = path.Remove (0, pos); src = Path.Combine (XamarinSourcePath, src); } else { Console.WriteLine ($"Ignoring path {path}"); return ""; } } return src; } /// /// Returns the source path for the bindings that were manually done. /// /// The source path for manual source. /// Path. string GetSourcePathForManualSource (string path) { var removalPath = $"/{FrameworkPath}/"; var srcFolder = Path.Combine ("src", FrameworkPath.Remove (FrameworkPath.IndexOf (".framework", StringComparison.InvariantCulture))) + Path.DirectorySeparatorChar; var pos = path.IndexOf (removalPath, StringComparison.InvariantCulture); var src = path.Remove (0, pos + FrameworkPath.Length + 2); pos = src.IndexOf (srcFolder, StringComparison.InvariantCulture); if (pos >= 0) src = src.Remove (0, src.IndexOf (srcFolder, StringComparison.InvariantCulture) + srcFolder.Length); else // we are dealing with a correct path (this does happen on the mac side) src = src.Remove (0, src.IndexOf ("/src/", StringComparison.InvariantCulture) + "/src/".Length); src = Path.Combine (XamarinSourcePath, src); return src; } string GetSourcePathForRuntimeSource (string path) { Console.WriteLine ($"Path is {path}"); if (path.StartsWith (InstallDir, StringComparison.Ordinal)) { var removalPath = Path.Combine (InstallDir, FrameworkPath.Replace(".framework", ""), "src"); Console.WriteLine ($"Removal path s {removalPath}"); var src = path.Remove (0, removalPath.Length); Console.WriteLine ($"Src is {src}"); if (src.StartsWith ("/", StringComparison.Ordinal)) src = src.Remove (0, 1); return Path.Combine (XamarinSourcePath.Replace ("src", "runtime"), src); } return path; } public string GetSourcePath(string path) { if (IsRunrime (path)) { return GetSourcePathForRuntimeSource (path); } // decide what type of path we are dealing with and return the correct source. if (IsGeneratedPath (path)) { return GetSourcePathForGeneratedPath (path); } if (IsManualSource (path)) return GetSourcePathForManualSource (path); return GetSourcePathForNativeType (path); } string GetTargetPathForGeneratedPath (string path) { var subpath = (InstallDir.Contains ("Xamarin.iOS.framework")) ? "native" : "full"; var pos = path.IndexOf (subpath, StringComparison.InvariantCulture); if (pos >= 0) { var relativePath = path.Remove (0, pos + subpath.Length + 1); return Path.Combine (DestinationDir, "src", FrameworkPath.Remove (FrameworkPath.IndexOf (".framework", StringComparison.InvariantCulture)), relativePath); } return null; } string GetTargetPathForManualSource (string path) { var pos = path.IndexOf (XamarinSourcePath, StringComparison.InvariantCulture); if (pos >= 0) { var relativePath = path.Remove (0, pos + XamarinSourcePath.Length); return Path.Combine (DestinationDir, "src", FrameworkPath.Remove (FrameworkPath.IndexOf (".framework", StringComparison.InvariantCulture)), relativePath); } return null; } string GetTargetPathForNativeType (string path) { var pos = path.IndexOf (NativeTypeSubpath, StringComparison.InvariantCulture); if (pos >= 0) { var relativePath = path.Remove (0, pos); return Path.Combine (DestinationDir, "src", FrameworkPath.Remove (FrameworkPath.IndexOf (".framework", StringComparison.InvariantCulture)), relativePath); } return null; } string GetTargetPathForRuntimeSource (string path) { var pos = path.IndexOf (RuntimeSubpath, StringComparison.InvariantCulture); if (pos >= 0) { var relativePath = path.Remove (0, pos + 1); // +1 is used to remove the leading / from RuntimeSubpath var result = Path.Combine (DestinationDir, "src", FrameworkPath.Remove (FrameworkPath.IndexOf (".framework", StringComparison.InvariantCulture)), relativePath); return result; } return null; } public string GetTargetPath (string path) { if (IsRunrime(path)) return GetTargetPathForRuntimeSource(path); if (IsGeneratedPath(path)) return GetTargetPathForGeneratedPath(path); if (IsManualSource(path)) return GetTargetPathForManualSource(path); return GetTargetPathForNativeType (path); } } }