Commits

roundcrisis committed fe890be Merge

Merge

Comments (0)

Files changed (5)

src/CodeShapes/ClassAnalyzer.cs

 		public IEnumerable<ICodeShape> Analyze<T>()
 		{
 			var shapes = FindAllPrivateMethods(typeof(T))
-				.Concat(FindAllPublicMethods(typeof(T)))
+				.Concat(FindMethods(typeof(T)))
 				.Concat(FindFields(typeof(T))).ToArray();
 
 			var methods = shapes.Where(s => s is MethodCodeShape).Cast<MethodCodeShape>();
 		public IEnumerable<FieldCodeShape> FindFields(Type type)
 		{
 			var fieldInfos = type.GetFields(BindingFlags.Public| BindingFlags.NonPublic| BindingFlags.Static| BindingFlags.Instance);
-			return fieldInfos.Select(fieldInfo => new FieldCodeShape(fieldInfo.Name, fieldInfo.IsPublic ? Visibility.Public : Visibility.NonPublic));
+			IList<FieldShape> fieldShapes = new List<FieldShape>();
+			foreach (var fieldInfo in fieldInfos)
+			{
+				var visibility = fieldInfo.IsPublic ? Visibility.Public : Visibility.NonPublic;
+				fieldShapes.Add(new FieldShape(fieldInfo.Name, visibility));
+			}
+			return fieldShapes.ToArray();
 		}
+		//todo: properties
+		private IEnumerable<IClassShape> FindMethods(Type type)
+		{
+			var privateProtectedInternalMethods = type.GetMethods( BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
+			var publicMethods = type.GetMethods();
 
-		private IEnumerable<ICodeShape> FindAllPrivateMethods(Type type)
-		{
-			var methodInfos = type.GetMethods( BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
-			return methodInfos.Select(methodInfo => new NonPublicMethodCodeShape(methodInfo, methodInfo.Name));
-		}
-
-		private IEnumerable<ICodeShape> FindAllPublicMethods(Type type)
-		{
-			return type.GetMethods().Select(methodInfo => new PublicMethodCodeShape(methodInfo, methodInfo.Name)).ToList();
+			List<MethodShape> result = privateProtectedInternalMethods.Select(methodInfo => new MethodShape(methodInfo, methodInfo.Name, Visibility.NonPublic)).ToList();
+			result.AddRange(publicMethods.Select(methodInfo => new MethodShape(methodInfo, methodInfo.Name, Visibility.Public)));
+			return result;
 		}
 	}
-}
+}

src/CodeShapes/CodeShapes.csproj

     <Compile Include="Shapes\FieldCodeShape.cs" />
     <Compile Include="Shapes\ICodeShape.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Shapes\MethodCodeShape.cs" />
-    <Compile Include="Shapes\NonPublicMethodCodeShape.cs" />
-    <Compile Include="Shapes\PublicMethodCodeShape.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
+    <Compile Include="Shapes\MethodShape.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
+</Project>

src/CodeShapes/Shapes/FieldShape.cs

+namespace CodeShapes.Shapes
+{
+	public class FieldShape : ClassShape
+	{
+		public Visibility Visibility { get; private set; }
+
+		public FieldShape(string fieldName, Visibility visibility) : base(fieldName)
+		{
+			Visibility = visibility;
+		}
+	}
+}

src/CodeShapes/Shapes/MethodShape.cs

+using System.Reflection;
+
+namespace CodeShapes.Shapes
+{
+	public class MethodShape : ClassShape
+	{
+		public MethodShape(MethodBase methodBase, string methodName, Visibility visibility)
+			: base(methodName)
+		{
+			MethodBase = methodBase;
+		}
+
+		public MethodShape(string methodName)
+			: base(methodName)
+		{}
+
+		public MethodBase MethodBase { get; private set; }
+
+		public Visibility Visibility { get; private set; }
+	}
+
+	public enum Visibility
+	{
+		Public,
+		NonPublic,
+		ProtectedMethod,
+		InternalMethod
+	}
+
+}

src/CodeShapesTests/ClassAnalizerTests.cs

+using System.Collections.Generic;
+using System.Linq;
+using CodeShapes;
+using CodeShapes.Shapes;
+using Xunit;
+
+namespace CodeShapesTests
+{
+	public class ClassAnalizerTests
+	{
+		private readonly ClassAnalyzer _classAnalyzer;
+
+		public ClassAnalizerTests()
+		{
+			_classAnalyzer = new ClassAnalyzer();
+		}
+
+		[Fact]
+		public void When_class_exists_then_it_doesnt_throw()
+		{
+			Assert.DoesNotThrow(() => _classAnalyzer.Analyze<SampleClass>());
+		}
+
+
+		[Fact]
+		public void When_there_is_fields_present_then_return()
+		{
+			var classShapes = _classAnalyzer.Analyze<SampleClass>();
+
+			IEnumerable<IClassShape> fields = classShapes.Where(x => x.GetType().Equals(typeof(FieldShape)));
+
+			Assert.Contains(typeof(SampleClass).GetFields().First().Name, fields.Select(x=>x.Name));
+		}
+
+
+		[Fact]
+		public void When_field_is_readonly_then_its_counted_anyway()
+		{
+			var classShapes = _classAnalyzer.Analyze<SampleClass>();
+
+			var fields = classShapes.Where(x => x.GetType().Equals(typeof(FieldShape)));
+			Assert.Equal(2, fields.Count());
+			
+		}
+
+		[Fact]
+		public void When_there_is_a_public_method_on_the_class_Then_finds_it()
+		{
+			var classShapes = _classAnalyzer.Analyze<SampleClass>();
+
+			var collection = classShapes.Where(x => x.GetType().Name == "PublicMethodShape");
+			Assert.Equal("CodeShapesMethod", collection.First().Name);
+		}
+
+		[Fact]
+		public void When_there_is_a_public_method_present_the_must_return_publicMethodShape()
+		{
+			var classShapes = _classAnalyzer.Analyze<SampleClass>();
+
+			Assert.True(classShapes.Any(x => x.GetType().Equals(typeof(MethodShape)) && ((MethodShape)x).Visibility == Visibility.Public));
+		}
+
+		[Fact]
+		public void When_there_is_a_private_method_present_the_must_return_privateMethodShape()
+		{
+			var classShapes = _classAnalyzer.Analyze<SampleClass>();
+
+			Assert.True(classShapes.Any(x => x.GetType().Equals(typeof(MethodShape)) && ((MethodShape)x).Visibility == Visibility.NonPublic));
+		}
+
+		[Fact]
+		public void When_there_is_a_recursive_method_the_adjacency_list_contains_itself_as_a_dependency()
+		{
+			var shapes = _classAnalyzer.Analyze<ClassWithRecursiveMethod>();
+
+			var methodShape = shapes.SingleOrDefault(s => s.Name == "ICallMyself");
+
+			Assert.NotNull(methodShape);
+
+			Assert.True(methodShape.AdjacencyList.Count == 1);
+			Assert.Same(methodShape, methodShape.AdjacencyList.Values.First());
+		}
+
+		[Fact]
+		public void Can_find_adjacency_from_private_to_public()
+		{
+			var shapes = _classAnalyzer.Analyze<ClassWithBiDirectionalDependency>();
+
+			IClassShape methodTwoShape = shapes.SingleOrDefault(s => s.Name == "MethodTwo");
+
+			Assert.NotEmpty(methodTwoShape.AdjacencyList.Values);
+			var methodTwoAdjacency = methodTwoShape.AdjacencyList.Values;
+
+
+			Assert.Equal("MethodOne", methodTwoAdjacency.First().Name);
+		}
+
+
+		[Fact]
+		public void When_there_is_a_bidirectional_dependency_between_methods_both_methods_adjacency_lists_contain_the_other()
+		{
+			var shapes = _classAnalyzer.Analyze<ClassWithBiDirectionalDependency>();
+
+			IClassShape methodOneShape = shapes.SingleOrDefault(s => s.Name == "MethodOne");
+			IClassShape methodTwoShape = shapes.SingleOrDefault(s => s.Name == "MethodTwo");
+
+			var methodOneAdjacency = methodOneShape.AdjacencyList.Values;
+			var methodTwoAdjacency = methodTwoShape.AdjacencyList.Values;
+
+			Assert.Equal(1, methodOneAdjacency.Count);
+			Assert.Same(methodOneAdjacency.First().Name, methodTwoShape.Name);
+			Assert.Same(methodTwoAdjacency.First().Name, methodOneShape.Name);
+		}
+
+		private class ClassWithBiDirectionalDependency
+		{
+			public void MethodOne()
+			{
+				MethodTwo();
+			}
+
+			private void MethodTwo()
+			{
+				MethodOne();
+			}
+		}
+
+		private class ClassWithRecursiveMethod
+		{
+			public void ICallMyself()
+			{
+				ICallMyself();
+			}
+		}
+	}
+}