Permalink
Browse files

First LCOM4 analyzer implementation

  • Loading branch information...
alexvictoor committed Jan 26, 2013
1 parent 4920615 commit 8e824bed380a223765978290c07b0690c2ce3982
@@ -36,6 +36,9 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="Mono.Cecil">
+ <HintPath>..\packages\Mono.Cecil.0.9.5.4\lib\net40\Mono.Cecil.dll</HintPath>
+ </Reference>
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
@@ -49,14 +52,9 @@
</ItemGroup>
<ItemGroup>
<Compile Include="DependencyParserTest.cs" />
+ <Compile Include="Lcom4AnalyzerTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\DependencyParser\DependencyParser.csproj">
- <Project>{AE47EF64-9F61-463A-9088-79907968A1FE}</Project>
- <Name>DependencyParser</Name>
- </ProjectReference>
- </ItemGroup>
<ItemGroup>
<Content Include="testdata\Example.Core.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@@ -71,6 +69,12 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\DependencyParser\DependencyParser.csproj">
+ <Project>{AE47EF64-9F61-463A-9088-79907968A1FE}</Project>
+ <Name>DependencyParser</Name>
+ </ProjectReference>
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -0,0 +1,230 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace DependencyParser.Test {
+
+
+ [NUnit.Framework.TestFixture]
+ public class Lcom4AnalyzerTest {
+ [Test]
+ public void Should_Find_One_Block_On_A_Simple_Class()
+ {
+ var analyzer = new Lcom4Analyzer();
+ var blocks = analyzer.FindLcomBlocks(getType("DependencyParser.Test.SimpleClass"));
+ Assert.AreEqual(1, blocks.Count);
+ }
+
+ [Test]
+ 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);
+ }
+
+ [Test]
+ public void Should_Treat_Accessors_As_Normal_Methods()
+ {
+ var analyzer = new Lcom4Analyzer();
+ var blocks = analyzer.FindLcomBlocks(getType("DependencyParser.Test.ClassWithProperties"));
+ Assert.AreEqual(2, blocks.Count);
+ }
+
+ [Test]
+ public void Should_Ignore_Constructors()
+ {
+ var analyzer = new Lcom4Analyzer();
+ var blocks = analyzer.FindLcomBlocks(getType("DependencyParser.Test.SimpleClassWithCtr"));
+ Assert.AreEqual(2, blocks.Count);
+ }
+
+ [Test]
+ public void Should_Not_Fail__On_Empty_Interface()
+ {
+ var analyzer = new Lcom4Analyzer();
+ var blocks = analyzer.FindLcomBlocks(getType("DependencyParser.Test.IEmpty"));
+ Assert.AreEqual(0, blocks.Count);
+ }
+
+ [Test]
+ public void Should_Not_Fail__On_Empty_Class()
+ {
+ var analyzer = new Lcom4Analyzer();
+ var blocks = analyzer.FindLcomBlocks(getType("DependencyParser.Test.EmptyClass"));
+ Assert.AreEqual(0, blocks.Count);
+ }
+
+ [Test]
+ public void Should_Not_Take_In_Account_Dispose_Methods()
+ {
+ var analyzer = new Lcom4Analyzer();
+ var blocks = analyzer.FindLcomBlocks(getType("DependencyParser.Test.SimpleDisposableClass"));
+ Assert.AreEqual(1, blocks.Count);
+ }
+
+ [Test]
+ public void Should_Not_Take_In_Account_Equals_Methods()
+ {
+ var analyzer = new Lcom4Analyzer();
+ var blocks = analyzer.FindLcomBlocks(getType("DependencyParser.Test.SimpleClassWithEquals"));
+ Assert.AreEqual(2, blocks.Count);
+ }
+
+ private TypeDefinition getType(string name)
+ {
+ string unit = Assembly.GetExecutingAssembly().Location;
+ var assembly = AssemblyDefinition.ReadAssembly(unit);
+ return assembly.MainModule.GetType(name);
+ }
+
+ }
+
+ public class EmptyClass
+ {
+
+ }
+
+ public interface IEmpty {
+
+ }
+
+ public class SimpleClass
+ {
+ private int counter;
+
+ public void Increment()
+ {
+ counter++;
+ }
+
+ public void Decrement()
+ {
+ counter--;
+ }
+ }
+
+ public class SimpleClassWithCtr {
+ private int fieldA;
+
+ private int fieldB;
+
+ public SimpleClassWithCtr()
+ {
+ fieldA = 42;
+ fieldB = 36;
+ }
+
+ public void doA()
+ {
+ fieldA++;
+ }
+
+ public void doB()
+ {
+ fieldB++;
+ }
+ }
+
+ public class ClassWithManyMethodsAndStrongCohesion {
+
+ public void doA()
+ {
+ Foo();
+ }
+
+ public void doB()
+ {
+ Foo();
+ Bar();
+ }
+
+
+ public void doC()
+ {
+ Bar();
+ }
+
+ private static void Foo()
+ {
+ Console.WriteLine("Whatever");
+ }
+
+ private static void Bar()
+ {
+ Console.WriteLine("Whatever");
+ }
+ }
+
+ public class ClassWithProperties {
+ public int Counter { get; set; }
+
+ public string Name { get; set; }
+ }
+
+ public class SimpleDisposableClass : IDisposable
+ {
+ public void doSomething()
+ {
+ Console.WriteLine("Whatever");
+ }
+
+ public void Dispose()
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class SimpleClassWithEquals {
+ private int fieldA;
+
+ private int fieldB;
+
+ public void doA()
+ {
+ fieldA++;
+ }
+
+ public void doB()
+ {
+ fieldB++;
+ }
+
+ public bool Equals(SimpleClassWithEquals other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return other.fieldA == fieldA && other.fieldB == fieldB;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != typeof (SimpleClassWithEquals)) return false;
+ return Equals((SimpleClassWithEquals) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (fieldA*397) ^ fieldB;
+ }
+ }
+
+ public static bool operator ==(SimpleClassWithEquals left, SimpleClassWithEquals right)
+ {
+ return Equals(left, right);
+ }
+
+ public static bool operator !=(SimpleClassWithEquals left, SimpleClassWithEquals right)
+ {
+ return !Equals(left, right);
+ }
+ }
+}
View
@@ -4,12 +4,16 @@ Microsoft Visual Studio Solution File, Format Version 11.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyParser", "DependencyParser\DependencyParser.csproj", "{AE47EF64-9F61-463A-9088-79907968A1FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyParser.Test", "DependencyParser.Test\DependencyParser.Test.csproj", "{F2D48840-011D-40D3-8CE9-6796A2FB237F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {AE47EF64-9F61-463A-9088-79907968A1FE} = {AE47EF64-9F61-463A-9088-79907968A1FE}
+ EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{9035F906-9992-4C15-9274-756884AC2259}"
ProjectSection(SolutionItems) = preProject
.nuget\NuGet.Config = .nuget\NuGet.Config
.nuget\NuGet.exe = .nuget\NuGet.exe
.nuget\NuGet.targets = .nuget\NuGet.targets
+ .nuget\packages.config = .nuget\packages.config
EndProjectSection
EndProject
Global
@@ -23,25 +27,29 @@ Global
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AE47EF64-9F61-463A-9088-79907968A1FE}.Debug|Any CPU.ActiveCfg = Debug|x86
- {AE47EF64-9F61-463A-9088-79907968A1FE}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
- {AE47EF64-9F61-463A-9088-79907968A1FE}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {AE47EF64-9F61-463A-9088-79907968A1FE}.Debug|Any CPU.Build.0 = Debug|x86
+ {AE47EF64-9F61-463A-9088-79907968A1FE}.Debug|Mixed Platforms.ActiveCfg = Release|x86
+ {AE47EF64-9F61-463A-9088-79907968A1FE}.Debug|Mixed Platforms.Build.0 = Release|x86
{AE47EF64-9F61-463A-9088-79907968A1FE}.Debug|x86.ActiveCfg = Debug|x86
{AE47EF64-9F61-463A-9088-79907968A1FE}.Debug|x86.Build.0 = Debug|x86
{AE47EF64-9F61-463A-9088-79907968A1FE}.Release|Any CPU.ActiveCfg = Release|x86
+ {AE47EF64-9F61-463A-9088-79907968A1FE}.Release|Any CPU.Build.0 = Release|x86
{AE47EF64-9F61-463A-9088-79907968A1FE}.Release|Mixed Platforms.ActiveCfg = Release|x86
{AE47EF64-9F61-463A-9088-79907968A1FE}.Release|Mixed Platforms.Build.0 = Release|x86
{AE47EF64-9F61-463A-9088-79907968A1FE}.Release|x86.ActiveCfg = Release|x86
{AE47EF64-9F61-463A-9088-79907968A1FE}.Release|x86.Build.0 = Release|x86
{F2D48840-011D-40D3-8CE9-6796A2FB237F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2D48840-011D-40D3-8CE9-6796A2FB237F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F2D48840-011D-40D3-8CE9-6796A2FB237F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {F2D48840-011D-40D3-8CE9-6796A2FB237F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {F2D48840-011D-40D3-8CE9-6796A2FB237F}.Debug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {F2D48840-011D-40D3-8CE9-6796A2FB237F}.Debug|Mixed Platforms.Build.0 = Release|Any CPU
{F2D48840-011D-40D3-8CE9-6796A2FB237F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F2D48840-011D-40D3-8CE9-6796A2FB237F}.Debug|x86.Build.0 = Debug|Any CPU
{F2D48840-011D-40D3-8CE9-6796A2FB237F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2D48840-011D-40D3-8CE9-6796A2FB237F}.Release|Any CPU.Build.0 = Release|Any CPU
{F2D48840-011D-40D3-8CE9-6796A2FB237F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{F2D48840-011D-40D3-8CE9-6796A2FB237F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{F2D48840-011D-40D3-8CE9-6796A2FB237F}.Release|x86.ActiveCfg = Release|Any CPU
+ {F2D48840-011D-40D3-8CE9-6796A2FB237F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -10,8 +10,9 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DependencyParser</RootNamespace>
<AssemblyName>DependencyParser</AssemblyName>
- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
- <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>
+ </TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
@@ -66,6 +67,9 @@
<Reference Include="NDesk.Options, Version=0.2.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NDesk.Options.0.2.1\lib\NDesk.Options.dll</HintPath>
</Reference>
+ <Reference Include="Gendarme.Framework">
+ <HintPath>..\packages\Mono.Gendarme.2.11.0.20121120\tools\Gendarme.Framework.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
@@ -74,12 +78,16 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="BiDictionary.cs" />
+ <Compile Include="Lcom4Analyzer.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
- <None Include="packages.config" />
+ <None Include="packages.config">
+ <SubType>Designer</SubType>
+ </None>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
Oops, something went wrong.

0 comments on commit 8e824be

Please sign in to comment.