PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/buildtools/CustomTasks/FxCop.cs

https://gitlab.com/vectorci/aws-sdk-net
C# | 226 lines | 165 code | 39 blank | 22 comment | 8 complexity | f09313dbce098be8ac712b819d7ab0f0 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.Build.Utilities;
  6. using System.IO;
  7. using System.Xml;
  8. using System.Reflection;
  9. namespace CustomTasks
  10. {
  11. public class UpdateFxCopProject : Task
  12. {
  13. public string Assemblies { get; set; }
  14. public string FxCopProject { get; set; }
  15. public string BinSuffix { get; set; }
  16. public override bool Execute()
  17. {
  18. if (string.IsNullOrEmpty(Assemblies))
  19. throw new ArgumentNullException("Assemblies");
  20. if (string.IsNullOrEmpty(FxCopProject))
  21. throw new ArgumentNullException("FxCopProject");
  22. if (string.IsNullOrEmpty(BinSuffix))
  23. throw new ArgumentNullException("BinSuffix");
  24. Assemblies = Path.GetFullPath(Assemblies);
  25. Log.LogMessage("Assemblies = " + Assemblies);
  26. FxCopProject = Path.GetFullPath(FxCopProject);
  27. Log.LogMessage("FxCopProject = " + FxCopProject);
  28. Log.LogMessage("Updating project...");
  29. FxCop.UpdateFxCopProject(Assemblies, FxCopProject, BinSuffix);
  30. Log.LogMessage("Project updated");
  31. return true;
  32. }
  33. }
  34. public static class FxCop
  35. {
  36. public static void UpdateFxCopProject(string assembliesFolder, string fxCopProjectPath, string binSuffix)
  37. {
  38. var allAssemblies = Directory.GetFiles(assembliesFolder, "*.dll").ToList();
  39. // move core assembly to the end of the list
  40. var coreAssembly = allAssemblies.Single(a => a.IndexOf(CoreAssemblyName, StringComparison.OrdinalIgnoreCase) >= 0);
  41. allAssemblies.Remove(coreAssembly);
  42. allAssemblies.Add(coreAssembly);
  43. var doc = new XmlDocument();
  44. doc.Load(fxCopProjectPath);
  45. var referenceDirectoriesNode = doc.SelectSingleNode(AssemblyReferenceDirectoriesXpath);
  46. var targetsNode = doc.SelectSingleNode(TargetsXpath);
  47. RemoveAllNodes(doc, targetsNode, TargetXpath);
  48. ResetReferenceDirectories(doc, referenceDirectoriesNode, DirectoriesXpath);
  49. foreach (var assembly in allAssemblies)
  50. {
  51. var assemblyName = Path.GetFileName(assembly).ToLower();
  52. var assemblyFolderName = assemblyName.Split('.')[1];
  53. var isCore = string.Equals(CoreAssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase);
  54. var newTarget = AddChildNode(targetsNode, "Target");
  55. AddAttribute(newTarget, "Name", MakeRelativePath(assembly));
  56. AddAttribute(newTarget, "Analyze", "True");
  57. var dirNode = AddChildNode(referenceDirectoriesNode, "Directory");
  58. if (isCore)
  59. {
  60. AddCoreAssembly(coreAssembly, newTarget);
  61. // Add assembly reference directory for Core
  62. // <Directory>$(ProjectDir)/src/Core/bin/Release/net35/</Directory>
  63. dirNode.InnerText = string.Format("$(ProjectDir)/src/Core/bin/Release/{0}/", binSuffix);
  64. }
  65. else
  66. {
  67. /*
  68. <Target Name="$(ProjectDir)/Deployment/assemblies/net35/AWSSDK.AutoScaling.dll" Analyze="True" AnalyzeAllChildren="True" />
  69. */
  70. AddAttribute(newTarget, "AnalyzeAllChildren", "True");
  71. // Add assembly reference directory for each service
  72. // <Directory>$(ProjectDir)/src/Services/MobileAnalytics/bin/Release/net35/</Directory>
  73. dirNode.InnerText = string.Format("$(ProjectDir)/src/Services/{0}/bin/Release/{1}/",
  74. assemblyFolderName, binSuffix);
  75. }
  76. }
  77. doc.Save(fxCopProjectPath);
  78. }
  79. private static void AddCoreAssembly(string coreAssemblyPath, XmlNode newTarget)
  80. {
  81. AddAttribute(newTarget, "AnalyzeAllChildren", "False");
  82. var assemblyName = Path.GetFileName(coreAssemblyPath).ToLower();
  83. var coreAssembly = Assembly.LoadFrom(coreAssemblyPath);
  84. /*
  85. <Target Name="$(ProjectDir)/Deployment/assemblies/net35/AWSSDK.Core.dll" Analyze="True" AnalyzeAllChildren="False">
  86. <Modules AnalyzeAllChildren="False">
  87. <Module Name="awssdk.core.dll" Analyze="True" AnalyzeAllChildren="False">
  88. <Namespaces AnalyzeAllChildren="False">
  89. <Namespace Name="" Analyze="True" AnalyzeAllChildren="True" />
  90. */
  91. var modulesNode = AddChildNode(newTarget, "Modules");
  92. AddAttribute(modulesNode, "AnalyzeAllChildren", "False");
  93. var moduleNode = AddChildNode(modulesNode, "Module");
  94. AddAttribute(moduleNode, "Name", assemblyName);
  95. AddAttribute(moduleNode, "Analyze", "True");
  96. AddAttribute(moduleNode, "AnalyzeAllChildren", "False");
  97. var namespacesNode = AddChildNode(moduleNode, "Namespaces");
  98. AddAttribute(namespacesNode, "AnalyzeAllChildren", "False");
  99. var namespaces = GetNamespacesToExamine(coreAssembly);
  100. foreach (var ns in namespaces.OrderBy(k => k, StringComparer.Ordinal))
  101. {
  102. var namespaceNode = AddChildNode(namespacesNode, "Namespace");
  103. AddAttribute(namespaceNode, "Name", ns);
  104. AddAttribute(namespaceNode, "Analyze", "True");
  105. AddAttribute(namespaceNode, "AnalyzeAllChildren", "True");
  106. }
  107. var resourcesNode = AddChildNode(moduleNode, "Resources");
  108. AddAttribute(resourcesNode, "AnalyzeAllChildren", "True");
  109. }
  110. public static HashSet<string> NamespacePrefixesToSkip = new HashSet<string>(StringComparer.Ordinal)
  111. {
  112. "ThirdParty.BouncyCastle",
  113. "ThirdParty.Ionic.Zlib",
  114. "ThirdParty.Json",
  115. };
  116. public const string NamespacesXpath = "FxCopProject/Targets/Target/Modules/Module/Namespaces";
  117. public const string TargetsXpath = "FxCopProject/Targets";
  118. public const string AssemblyReferenceDirectoriesXpath = "FxCopProject/Targets/AssemblyReferenceDirectories";
  119. public const string DirectoriesXpath = "FxCopProject/Targets/AssemblyReferenceDirectories/Directory";
  120. public const string TargetXpath = "FxCopProject/Targets/Target";
  121. public const string CoreAssemblyName = "AWSSDK.Core.dll";
  122. public const string DeploymentPath = @"Deployment\assemblies";
  123. public const string ProjectDirRelative = @"$(ProjectDir)\..\";
  124. public static IEnumerable<string> GetNamespacesToExamine(Assembly assembly)
  125. {
  126. HashSet<string> namespaces = new HashSet<string>(StringComparer.Ordinal);
  127. var allTypes = assembly.GetTypes().ToList();
  128. foreach (var type in allTypes)
  129. {
  130. var ns = type.Namespace;
  131. if (ShouldSkip(ns))
  132. continue;
  133. namespaces.Add(ns);
  134. }
  135. return namespaces;
  136. }
  137. private static bool ShouldSkip(string ns)
  138. {
  139. if (ns == null)
  140. return false;
  141. foreach (var toSkip in NamespacePrefixesToSkip)
  142. if (ns.StartsWith(toSkip, StringComparison.Ordinal))
  143. return true;
  144. return false;
  145. }
  146. private static string MakeRelativePath(string assemblyPath)
  147. {
  148. var fullPath = Path.GetFullPath(assemblyPath);
  149. var deploymentIndex = fullPath.IndexOf(DeploymentPath, StringComparison.OrdinalIgnoreCase);
  150. var partialPath = fullPath.Substring(deploymentIndex);
  151. var relativePath = string.Concat(ProjectDirRelative, partialPath);
  152. return relativePath;
  153. }
  154. private static void AddAttribute(XmlNode node, string name, string value)
  155. {
  156. var doc = node.OwnerDocument;
  157. var attribute = doc.CreateAttribute(name);
  158. attribute.Value = value;
  159. node.Attributes.Append(attribute);
  160. }
  161. private static XmlNode AddChildNode(XmlNode parent, string name)
  162. {
  163. var doc = parent.OwnerDocument;
  164. var node = doc.CreateElement(name);
  165. parent.AppendChild(node);
  166. return node;
  167. }
  168. private static void RemoveAllNodes(XmlDocument doc, XmlNode targetsNode, string xpath)
  169. {
  170. var matchingNodes = doc.SelectNodes(xpath);
  171. foreach (XmlNode node in matchingNodes)
  172. targetsNode.RemoveChild(node);
  173. }
  174. private static void ResetReferenceDirectories(XmlDocument doc,
  175. XmlNode referenceDirectoriesNode, string xpath)
  176. {
  177. RemoveAllNodes(doc, referenceDirectoriesNode, xpath);
  178. //// Add default reference paths
  179. //var wp8DirNode = AddChildNode(referenceDirectoriesNode, "Directory");
  180. //wp8DirNode.InnerText = "$(ProjectDir)/Deployment/wp8/";
  181. //var winrtDirNode = AddChildNode(referenceDirectoriesNode, "Directory");
  182. //winrtDirNode.InnerText = "$(ProjectDir)/Deployment/winrt/";
  183. //var dotnet45DirNode = AddChildNode(referenceDirectoriesNode, "Directory");
  184. //dotnet45DirNode.InnerText = "$(ProjectDir)/Deployment/dotnet45/";
  185. }
  186. }
  187. }