|
|
|
@ -5,7 +5,6 @@ using System;
@@ -5,7 +5,6 @@ using System;
|
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Collections.ObjectModel; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Reflection; |
|
|
|
|
using ICSharpCode.CodeQuality.Engine.Dom; |
|
|
|
|
using ICSharpCode.NRefactory.TypeSystem; |
|
|
|
|
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
|
|
|
@ -18,13 +17,14 @@ namespace ICSharpCode.CodeQuality.Engine
@@ -18,13 +17,14 @@ namespace ICSharpCode.CodeQuality.Engine
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class AssemblyAnalyzer |
|
|
|
|
{ |
|
|
|
|
CecilLoader loader = new CecilLoader(true); |
|
|
|
|
CecilLoader loader = new CecilLoader(true) { IncludeInternalMembers = true }; |
|
|
|
|
ICompilation compilation; |
|
|
|
|
Dictionary<IAssembly, AssemblyNode> assemblyMappings; |
|
|
|
|
Dictionary<string, NamespaceNode> namespaceMappings; |
|
|
|
|
Dictionary<ITypeDefinition, TypeNode> typeMappings; |
|
|
|
|
Dictionary<IMethod, MethodNode> methodMappings; |
|
|
|
|
Dictionary<IField, FieldNode> fieldMappings; |
|
|
|
|
internal Dictionary<IAssembly, AssemblyNode> assemblyMappings; |
|
|
|
|
internal Dictionary<string, NamespaceNode> namespaceMappings; |
|
|
|
|
internal Dictionary<ITypeDefinition, TypeNode> typeMappings; |
|
|
|
|
internal Dictionary<IMethod, MethodNode> methodMappings; |
|
|
|
|
internal Dictionary<IField, FieldNode> fieldMappings; |
|
|
|
|
internal Dictionary<MemberReference, IEntity> cecilMappings; |
|
|
|
|
List<string> fileNames; |
|
|
|
|
|
|
|
|
|
public AssemblyAnalyzer() |
|
|
|
@ -45,25 +45,54 @@ namespace ICSharpCode.CodeQuality.Engine
@@ -45,25 +45,54 @@ namespace ICSharpCode.CodeQuality.Engine
|
|
|
|
|
assemblyMappings = new Dictionary<IAssembly, AssemblyNode>(); |
|
|
|
|
namespaceMappings = new Dictionary<string, NamespaceNode>(); |
|
|
|
|
typeMappings = new Dictionary<ITypeDefinition, TypeNode>(); |
|
|
|
|
fieldMappings = new Dictionary<IField, FieldNode>(); |
|
|
|
|
methodMappings = new Dictionary<IMethod, MethodNode>(); |
|
|
|
|
cecilMappings = new Dictionary<MemberReference, IEntity>(); |
|
|
|
|
|
|
|
|
|
foreach (var type in compilation.GetAllTypeDefinitions()) { |
|
|
|
|
AnalyzeType(type); |
|
|
|
|
ReadType(type); |
|
|
|
|
} |
|
|
|
|
foreach (TypeNode type in typeMappings.Values) { |
|
|
|
|
foreach (var field in type.TypeDefinition.Fields) { |
|
|
|
|
var node = new FieldNode(field); |
|
|
|
|
fieldMappings.Add(field, node); |
|
|
|
|
try { |
|
|
|
|
var cecilObj = loader.GetCecilObject((IUnresolvedField)field.UnresolvedMember); |
|
|
|
|
cecilMappings[cecilObj] = field; |
|
|
|
|
} catch (InvalidOperationException) {} |
|
|
|
|
type.Children.Add(node); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
foreach (var method in type.TypeDefinition.Methods) { |
|
|
|
|
var node = new MethodNode(method); |
|
|
|
|
methodMappings.Add(method, node); |
|
|
|
|
try { |
|
|
|
|
var cecilObj = loader.GetCecilObject((IUnresolvedMethod)method.UnresolvedMember); |
|
|
|
|
cecilMappings[cecilObj] = method; |
|
|
|
|
} catch (InvalidOperationException) {} |
|
|
|
|
type.Children.Add(node); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
ILAnalyzer analyzer = new ILAnalyzer(loadedAssemblies.Select(asm => loader.GetCecilObject(asm)).ToArray(), this); |
|
|
|
|
foreach (var element in methodMappings) { |
|
|
|
|
int cc; |
|
|
|
|
try { |
|
|
|
|
var cecilObj = loader.GetCecilObject((IUnresolvedMethod)element.Key.UnresolvedMember); |
|
|
|
|
analyzer.Analyze(cecilObj.Body, element.Value, out cc); |
|
|
|
|
} catch (InvalidOperationException) {} |
|
|
|
|
} |
|
|
|
|
return new ReadOnlyCollection<AssemblyNode>(assemblyMappings.Values.ToList()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IEnumerable<IUnresolvedAssembly> LoadAssemblies() |
|
|
|
|
{ |
|
|
|
|
var resolver = new DefaultAssemblyResolver(); |
|
|
|
|
foreach (var file in fileNames) { |
|
|
|
|
var mainAsm = loader.LoadAssemblyFile(file); |
|
|
|
|
yield return mainAsm; |
|
|
|
|
var referencedAssemblies = loader.GetCecilObject(mainAsm).Modules |
|
|
|
|
.SelectMany(m => m.AssemblyReferences) |
|
|
|
|
.Select(r => resolver.Resolve(r)); |
|
|
|
|
foreach (var asm in referencedAssemblies) |
|
|
|
|
yield return loader.LoadAssembly(asm); |
|
|
|
|
} |
|
|
|
|
var resolver = new AssemblyResolver(); |
|
|
|
|
List<AssemblyDefinition> assemblies = new List<AssemblyDefinition>(); |
|
|
|
|
foreach (var file in fileNames.Distinct(StringComparer.OrdinalIgnoreCase)) |
|
|
|
|
assemblies.Add(resolver.LoadAssemblyFile(file)); |
|
|
|
|
foreach (var asm in assemblies.ToArray()) |
|
|
|
|
assemblies.AddRange(asm.Modules.SelectMany(m => m.AssemblyReferences).Select(r => resolver.Resolve(r))); |
|
|
|
|
return assemblies.Distinct().Select(asm => loader.LoadAssembly(asm)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
NamespaceNode GetOrCreateNamespace(AssemblyNode assembly, string namespaceName) |
|
|
|
@ -88,13 +117,31 @@ namespace ICSharpCode.CodeQuality.Engine
@@ -88,13 +117,31 @@ namespace ICSharpCode.CodeQuality.Engine
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AnalyzeType(ITypeDefinition type) |
|
|
|
|
void ReadType(ITypeDefinition type) |
|
|
|
|
{ |
|
|
|
|
var asm = GetOrCreateAssembly(type.ParentAssembly); |
|
|
|
|
var ns = GetOrCreateNamespace(asm, type.Namespace); |
|
|
|
|
TypeNode parent; |
|
|
|
|
var node = new TypeNode(type); |
|
|
|
|
if (type.DeclaringTypeDefinition != null) { |
|
|
|
|
if (typeMappings.TryGetValue(type.DeclaringTypeDefinition, out parent)) |
|
|
|
|
parent.Children.Add(node); |
|
|
|
|
else |
|
|
|
|
throw new Exception("TypeNode not found: " + type.DeclaringTypeDefinition.FullName); |
|
|
|
|
} else |
|
|
|
|
ns.Children.Add(node); |
|
|
|
|
cecilMappings[loader.GetCecilObject(type.Parts.First())] = type; |
|
|
|
|
typeMappings.Add(type, node); |
|
|
|
|
ns.Children.Add(node); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class AssemblyResolver : DefaultAssemblyResolver |
|
|
|
|
{ |
|
|
|
|
public AssemblyDefinition LoadAssemblyFile(string fileName) |
|
|
|
|
{ |
|
|
|
|
var assembly = AssemblyDefinition.ReadAssembly(fileName, new ReaderParameters { AssemblyResolver = this }); |
|
|
|
|
RegisterAssembly(assembly); |
|
|
|
|
return assembly; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|