Permalink
Browse files

Add LCOM4 blocks to the XML output

  • Loading branch information...
1 parent 9d1bedd commit 28ee04b235f595a582e9c8c9248ebcc810cb50bd @alexvictoor alexvictoor committed Jan 27, 2013
View
4 DependencyParser.Test/DependencyParser.Test.csproj
@@ -53,9 +53,13 @@
<ItemGroup>
<Compile Include="DependencyParserTest.cs" />
<Compile Include="Lcom4AnalyzerTest.cs" />
+ <Compile Include="Lcom4WriterTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
+ <Content Include="lcom4-expected.xml">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
<Content Include="testdata\Example.Core.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
View
32 DependencyParser.Test/Lcom4AnalyzerTest.cs
@@ -25,6 +25,7 @@ public void Should_Find_One_Block_On_A_Class_With_Strong_Cohesion()
var analyzer = new Lcom4Analyzer();
var blocks = analyzer.FindLcomBlocks(getType("DependencyParser.Test.ClassWithManyMethodsAndStrongCohesion"));
Assert.AreEqual(1, blocks.Count);
+ Assert.AreEqual(5, blocks.ElementAt(0).Count);
}
[Test]
@@ -75,6 +76,14 @@ public void Should_Not_Take_In_Account_Equals_Methods()
Assert.AreEqual(2, blocks.Count);
}
+ [Test]
+ public void Should_Not_Take_In_Account_ToString_Methods()
+ {
+ var analyzer = new Lcom4Analyzer();
+ var blocks = analyzer.FindLcomBlocks(getType("DependencyParser.Test.SimpleClassWithToString"));
+ Assert.AreEqual(2, blocks.Count);
+ }
+
private TypeDefinition getType(string name)
{
string unit = Assembly.GetExecutingAssembly().Location;
@@ -151,7 +160,7 @@ public void doC()
private static void Foo()
{
- Console.WriteLine("Whatever");
+ Console.WriteLine("Whatever".ToLower());
}
private static void Bar()
@@ -227,4 +236,25 @@ public override int GetHashCode()
return !Equals(left, right);
}
}
+
+ public class SimpleClassWithToString {
+ private int fieldA;
+
+ private int fieldB;
+
+ public void doA()
+ {
+ fieldA++;
+ }
+
+ public void doB()
+ {
+ fieldB++;
+ }
+
+ public override string ToString()
+ {
+ return fieldA + " " + fieldB;
+ }
+ }
}
View
63 DependencyParser.Test/Lcom4WriterTest.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Xml;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace DependencyParser.Test {
+
+ [NUnit.Framework.TestFixture]
+ public class Lcom4WriterTest {
+ [Test]
+ public void Should_Generate()
+ {
+ File.Delete("lcom4-generated.xml");
+ using (var stream = new FileStream("lcom4-generated.xml", FileMode.Create))
+ {
+ using (var writer = new XmlTextWriter(stream, Encoding.UTF8))
+ {
+ var lcom4Writer = new Lcom4Writer();
+ var typeDefinition = getType("DependencyParser.Test.SimpleClassWithTwoFields");
+ var blocks = new HashSet<HashSet<MemberReference>>();
+ foreach (var mth in typeDefinition.Methods)
+ {
+ var block = new HashSet<MemberReference> {mth};
+ blocks.Add(block);
+ }
+ lcom4Writer.Write(writer, typeDefinition, blocks);
+ }
+ }
+ string expected = File.ReadAllText("lcom4-expected.xml");
+ string result = File.ReadAllText("lcom4-generated.xml");
+
+ Assert.AreEqual(expected, result);
+ }
+
+ private TypeDefinition getType(string name)
+ {
+ string unit = Assembly.GetExecutingAssembly().Location;
+ var assembly = AssemblyDefinition.ReadAssembly(unit);
+ return assembly.MainModule.GetType(name);
+ }
+ }
+
+ public class SimpleClassWithTwoFields {
+ private int fieldA;
+
+ private int fieldB;
+
+ public void doA()
+ {
+ fieldA++;
+ }
+
+ public void doB()
+ {
+ fieldB++;
+ }
+ }
+}
View
1 DependencyParser.Test/lcom4-expected.xml
@@ -0,0 +1 @@
+<type fullName="DependencyParser.Test.SimpleClassWithTwoFields"><block><element type="Method" name="System.Void doA()" /></block><block><element type="Method" name="System.Void doB()" /></block><block><element type="Method" name="System.Void .ctor()" /></block></type>
View
63 DependencyParser.Test/testdata/test.xml
@@ -24,5 +24,68 @@
<From fullname="Example.Core.SampleMeasure/Possible" />
<From fullname="Example.Core.SampleMeasure" />
</TypeReferences>
+ <lcom4>
+ <type fullName="&lt;Module&gt;" />
+ <type fullName="Example.Core.IMoney" />
+ <type fullName="Example.Core.Model.SubType">
+ <block>
+ <element type="Method" name="System.String get_Name()" />
+ <element type="Field" name="&lt;Name&gt;k__BackingField" />
+ <element type="Method" name="System.Void set_Name(System.String)" />
+ </block>
+ </type>
+ <type fullName="Example.Core.Money">
+ <block>
+ <element type="Method" name="Example.Core.IMoney Add(Example.Core.IMoney)" />
+ <element type="Method" name="Example.Core.IMoney Subtract(Example.Core.IMoney)" />
+ </block>
+ <block>
+ <element type="Method" name="Example.Core.IMoney AddMoney(Example.Core.Money)" />
+ <element type="Method" name="System.String get_Currency()" />
+ <element type="Method" name="System.Int32 get_Amount()" />
+ <element type="Field" name="fAmount" />
+ <element type="Field" name="fCurrency" />
+ <element type="Method" name="System.Boolean get_IsZero()" />
+ <element type="Method" name="Example.Core.IMoney Multiply(System.Int32)" />
+ <element type="Method" name="Example.Core.IMoney Negate()" />
+ </block>
+ <block>
+ <element type="Method" name="Example.Core.IMoney AddMoneyBag(Example.Core.MoneyBag)" />
+ </block>
+ </type>
+ <type fullName="Example.Core.Alex" />
+ <type fullName="Example.Core.MoneyBag">
+ <block>
+ <element type="Method" name="Example.Core.IMoney Add(Example.Core.IMoney)" />
+ <element type="Method" name="Example.Core.IMoney Subtract(Example.Core.IMoney)" />
+ </block>
+ <block>
+ <element type="Method" name="Example.Core.IMoney AddMoney(Example.Core.Money)" />
+ <element type="Method" name="Example.Core.IMoney Simplify()" />
+ <element type="Method" name="Example.Core.IMoney AddMoneyBag(Example.Core.MoneyBag)" />
+ <element type="Method" name="System.Void AppendBag(Example.Core.MoneyBag)" />
+ <element type="Field" name="fMonies" />
+ <element type="Method" name="System.Void AppendMoney(Example.Core.Money)" />
+ <element type="Method" name="Example.Core.Money FindMoney(System.String)" />
+ <element type="Method" name="System.Boolean Contains(Example.Core.Money)" />
+ <element type="Method" name="System.Boolean get_IsZero()" />
+ <element type="Method" name="Example.Core.IMoney Multiply(System.Int32)" />
+ <element type="Method" name="Example.Core.IMoney Negate()" />
+ </block>
+ </type>
+ <type fullName="Example.Core.SampleMeasure">
+ <block>
+ <element type="Method" name="System.Int32 get_Size()" />
+ <element type="Field" name="&lt;Size&gt;k__BackingField" />
+ <element type="Method" name="System.Void set_Size(System.Int32)" />
+ <element type="Method" name="System.String Compute()" />
+ <element type="Field" name="actual" />
+ <element type="Method" name="System.String Compute(System.String)" />
+ </block>
+ <block>
+ <element type="Method" name="System.String Compute(System.Int32)" />
+ </block>
+ </type>
+ </lcom4>
</Assembly>
</Dependencies>
View
1 DependencyParser/DependencyParser.csproj
@@ -79,6 +79,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Lcom4Analyzer.cs" />
+ <Compile Include="Lcom4Writer.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
View
12 DependencyParser/Lcom4Analyzer.cs
@@ -21,7 +21,7 @@ public HashSet<HashSet<MemberReference>> FindLcomBlocks(TypeDefinition t)
var memberBlocks = new Dictionary<MemberReference, HashSet<MemberReference>>();
foreach (var method in t.Methods)
{
- if (NeedToBeFiltered(method))
+ if (NeedToBeFiltered(t, method))
{
continue;
}
@@ -53,7 +53,7 @@ public HashSet<HashSet<MemberReference>> FindLcomBlocks(TypeDefinition t)
case OperandType.InlineMethod:
// special case for automatic properties since the 'backing' fields won't be used
MethodDefinition md = inst.Operand as MethodDefinition;
- if (md != null && !NeedToBeFiltered(md))
+ if (md != null && !NeedToBeFiltered(t, md))
{
mr = md;
}
@@ -80,14 +80,16 @@ public HashSet<HashSet<MemberReference>> FindLcomBlocks(TypeDefinition t)
return MergeBlocks(memberBlocks.Values);
}
- private bool NeedToBeFiltered(MethodDefinition method)
+ private bool NeedToBeFiltered(TypeDefinition t, MethodDefinition method)
{
- return !method.HasBody
+ return t != method.DeclaringType
+ ||!method.HasBody
|| (method.IsGeneratedCode() && !method.IsSetter && !method.IsGetter)
|| method.IsConstructor
|| (method.IsSpecialName && !method.IsSetter && !method.IsGetter)
|| "Dispose" == method.Name
- || "Equals" == method.Name
+ || "ToString" == method.Name
+ || "Equals" == method.Name
|| "GetHashCode" == method.Name;
}
View
67 DependencyParser/Lcom4Writer.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml;
+using Mono.Cecil;
+
+namespace DependencyParser {
+
+
+ /// <summary>
+ /// TODO: Update summary.
+ /// </summary>
+ public class Lcom4Writer {
+
+ public void Write(XmlTextWriter xml, TypeDefinition type, IEnumerable<IEnumerable<MemberReference>> blocks)
+ {
+ xml.WriteStartElement("type");
+ xml.WriteAttributeString("fullName", type.FullName);
+ foreach (var block in blocks)
+ {
+ xml.WriteStartElement("block");
+ foreach (var memberReference in block)
+ {
+ xml.WriteStartElement("element");
+ var method = memberReference as MethodDefinition;
+ string name;
+ string elementType;
+ if (method == null)
+ {
+ elementType = "Field";
+ name = memberReference.Name;
+ } else
+ {
+ elementType = "Method";
+ name = BuildSignature(method);
+ }
+ xml.WriteAttributeString("type", elementType);
+ xml.WriteAttributeString("name", name);
+ xml.WriteEndElement();
+ }
+ xml.WriteEndElement();
+ }
+ xml.WriteEndElement();
+ }
+
+ private string BuildSignature(MethodDefinition mth)
+ {
+ var builder = new StringBuilder();
+ builder.Append(mth.ReturnType);
+ builder.Append(" ");
+ builder.Append(mth.Name);
+ builder.Append("(");
+ var parameters = mth.Parameters;
+ for (int i = 0; i < parameters.Count; i++)
+ {
+ builder.Append(parameters[i].ParameterType.FullName);
+ if (i < (parameters.Count-1))
+ {
+ builder.Append(", ");
+ }
+ }
+ builder.Append(")");
+ return builder.ToString();
+ }
+ }
+}
View
17 DependencyParser/Program.cs
@@ -15,7 +15,11 @@ public class Program
private static readonly List<string> Parsed = new List<string>();
private static readonly List<string> ToParse = new List<string>();
-
+
+ private static readonly Lcom4Analyzer lcom4Analyzer = new Lcom4Analyzer();
+
+ private static readonly Lcom4Writer lcom4Writer = new Lcom4Writer();
+
public static void Main(string[] args)
{
bool showHelp = false;
@@ -162,6 +166,11 @@ static void Analysis(XmlTextWriter writer, ModuleDefinition module, string fullP
}
writer.WriteEndElement();
+ writer.WriteStartElement("lcom4");
+ foreach (var t in module.Types) {
+ ParseTypeLcom4Blocks(writer, t);
+ }
+ writer.WriteEndElement();
}
writer.WriteEndElement();
@@ -174,6 +183,12 @@ static void Analysis(XmlTextWriter writer, ModuleDefinition module, string fullP
Parsed.Add(module.Assembly.Name.FullName);
}
+ public static void ParseTypeLcom4Blocks(XmlTextWriter writer, TypeDefinition t)
+ {
+ var blocks = lcom4Analyzer.FindLcomBlocks(t);
+ lcom4Writer.Write(writer, t, blocks);
+ }
+
public static void ParseType(XmlTextWriter writer, TypeDefinition t)
{
// ignore generated types

0 comments on commit 28ee04b

Please sign in to comment.