PageRenderTime 38ms CodeModel.GetById 23ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/buildtools/CustomTasks/FxCop.cs

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