Skip to content

Commit

Permalink
Adding support for constructors in class generation for reflection
Browse files Browse the repository at this point in the history
Class AST node factory was ignoring constructors. Added support and
added tests too.

Targets #41
  • Loading branch information
andry-tino committed May 18, 2017
1 parent 4c0efd1 commit a41f6f9
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 32 deletions.
1 change: 1 addition & 0 deletions src/Reflection/Reflection.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
<Compile Include="ASTBuilder.cs" />
<Compile Include="ASTInfo.cs" />
<Compile Include="factories\ClassDeclarationSyntaxFactory.cs" />
<Compile Include="factories\ConstructorDeclarationSyntaxFactory.cs" />
<Compile Include="factories\MethodDeclarationSyntaxFactory.cs" />
<Compile Include="helpers\ObjectClass.cs" />
<Compile Include="helpers\Visibility.cs" />
Expand Down
5 changes: 0 additions & 5 deletions src/Reflection/assembly-proxying/IMethodBaseProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ namespace Rosetta.Reflection.Proxies
/// </summary>
public interface IMethodBaseProxy
{
/// <summary>
/// Gets the name of the current member.
/// </summary>
string Name { get; }

/// <summary>
/// Gets the parameters of the specified method or constructor.
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions src/Reflection/assembly-proxying/IMethodInfoProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ namespace Rosetta.Reflection.Proxies
/// </summary>
public interface IMethodInfoProxy : IMethodBaseProxy
{
/// <summary>
/// Gets the name of the current member.
/// </summary>
string Name { get; }

/// <summary>
/// Gets the return type of this method.
/// </summary>
Expand Down
19 changes: 9 additions & 10 deletions src/Reflection/factories/ClassDeclarationSyntaxFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,15 @@ public ClassDeclarationSyntax Create()
}

// Constructors
// TODO: Enable
//var ctors = type.DeclaredMethods;

//if (ctors != null)
//{
// foreach (var ctor in ctors)
// {
// classNode.AddMembers(SyntaxFactory.ConstructorDeclaration());
// }
//}
var ctors = this.classInfo.DeclaredConstructors;

if (ctors != null)
{
foreach (var ctor in ctors)
{
classNode = classNode.AddMembers(new ConstructorDeclarationSyntaxFactory(ctor, this.classInfo).Create());
}
}

// Methods
var methods = this.classInfo.DeclaredMethods;
Expand Down
75 changes: 75 additions & 0 deletions src/Reflection/factories/ConstructorDeclarationSyntaxFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/// <summary>
/// ConstructorDeclarationSyntaxFactory.cs
/// Andrea Tino - 2017
/// </summary>

namespace Rosetta.Reflection.Factories
{
using System;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

using Rosetta.Reflection.Helpers;
using Rosetta.Reflection.Proxies;

/// <summary>
/// Factory for generating a <see cref="ConstructorDeclarationSyntax"/>.
/// </summary>
public class ConstructorDeclarationSyntaxFactory
{
private ITypeInfoProxy classInfo;
private IConstructorInfoProxy ctorInfo;

/// <summary>
/// Initializes a new instance of the <see cref="ConstructorDeclarationSyntaxFactory"/> class.
/// </summary>
/// <param name="ctorInfo"></param>
/// <param name="classInfo"></param>
public ConstructorDeclarationSyntaxFactory(IConstructorInfoProxy ctorInfo, ITypeInfoProxy classInfo)
{
if (ctorInfo == null)
{
throw new ArgumentNullException(nameof(ctorInfo));
}

if (classInfo == null)
{
throw new ArgumentNullException(nameof(classInfo));
}

this.ctorInfo = ctorInfo;
this.classInfo = classInfo;
}

/// <summary>
/// Creates the <see cref="ConstructorDeclarationSyntax"/>.
/// </summary>
/// <returns></returns>
public ConstructorDeclarationSyntax Create()
{
var ctorDeclaration = SyntaxFactory.ConstructorDeclaration(this.classInfo.Name);

// Defining accessibility
ctorDeclaration = ctorDeclaration.AddModifiers(SyntaxFactory.Token(new Visibility(this.ctorInfo).Token));

// Defining parameters
var parameters = this.ctorInfo.Parameters;

if (parameters != null)
{
foreach (var parameter in parameters)
{
ctorDeclaration = ctorDeclaration.AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.Identifier(parameter.Name))
.WithType(SyntaxFactory.ParseTypeName(parameter.ParameterType.FullName)));
}
}

// Dummy body
ctorDeclaration = ctorDeclaration.WithBody(DummyBody.GenerateForMerhod());

return ctorDeclaration;
}
}
}
2 changes: 1 addition & 1 deletion src/Reflection/factories/MethodDeclarationSyntaxFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class MethodDeclarationSyntaxFactory
/// <summary>
/// Initializes a new instance of the <see cref="MethodDeclarationSyntaxFactory"/> class.
/// </summary>
/// <param name="classInfo"></param>
/// <param name="methodInfo"></param>
public MethodDeclarationSyntaxFactory(IMethodInfoProxy methodInfo)
{
if (methodInfo == null)
Expand Down
20 changes: 10 additions & 10 deletions src/Reflection/helpers/Visibility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,20 @@ namespace Rosetta.Reflection.Helpers
public class Visibility
{
private readonly ITypeInfoProxy type;
private readonly IMethodInfoProxy method;
private readonly IMethodBaseProxy methodBase;

/// <summary>
/// Initializes a new instance of the <see cref="Visibility"/> class.
/// </summary>
/// <param name="method">The <see cref="IMethodInfoProxy"/> to analyze.</param>
public Visibility(IMethodInfoProxy method)
/// <param name="methodBase">The <see cref="IMethodBaseProxy"/> to analyze.</param>
public Visibility(IMethodBaseProxy methodBase)
{
if (method == null)
if (methodBase == null)
{
throw new ArgumentNullException(nameof(method));
throw new ArgumentNullException(nameof(methodBase));
}

this.method = method;
this.methodBase = methodBase;
}

/// <summary>
Expand All @@ -56,11 +56,11 @@ public SyntaxKind Token
{
get
{
if (this.method != null)
if (this.methodBase != null)
{
if (this.method.IsPrivate) return SyntaxKind.PrivateKeyword;
if (this.method.IsFamily) return SyntaxKind.ProtectedKeyword;
if (this.method.IsPublic) return SyntaxKind.PublicKeyword;
if (this.methodBase.IsPrivate) return SyntaxKind.PrivateKeyword;
if (this.methodBase.IsFamily) return SyntaxKind.ProtectedKeyword;
if (this.methodBase.IsPublic) return SyntaxKind.PublicKeyword;

// Methods in classes are by default private unless otherwise specify
return SyntaxKind.PrivateKeyword;
Expand Down
1 change: 1 addition & 0 deletions test/Reflection.UnitTests/Reflection.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
<ItemGroup>
<Compile Include="Class.cs" />
<Compile Include="factories\ClassDeclarationSyntaxFactoryTest.cs" />
<Compile Include="factories\ConstructorDeclarationSyntaxFactoryTest.cs" />
<Compile Include="factories\MethodDeclarationSyntaxFactoryTest.cs" />
<Compile Include="helpers\ObjectClassTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down
20 changes: 20 additions & 0 deletions test/Reflection.UnitTests/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Rosetta.Reflection.UnitTests
{
using System;
using System.IO;
using System.Linq;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
Expand Down Expand Up @@ -80,6 +81,25 @@ public static IMethodInfoProxy LocateMethod(this ITypeInfoProxy type, string met
return null;
}

/// <summary>
/// Finds a <see cref="IConstructorInfoProxy"/> into an <see cref="ITypeInfoProxy"/>.
/// </summary>
/// <param name="type"></param>
/// <param name="argsNum"></param>
/// <returns></returns>
public static IConstructorInfoProxy LocateConstructor(this ITypeInfoProxy type, int argsNum)
{
foreach (var ctor in type.DeclaredConstructors)
{
if ((argsNum == 0 && ctor.Parameters == null) || ctor.Parameters.Count() == argsNum)
{
return ctor;
}
}

return null;
}

/// <summary>
/// Checks that a modifier is present in the list.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace Rosetta.Reflection.UnitTests
public class ClassDeclarationSyntaxFactoryTest
{
[TestMethod]
public void ClassNameCorrectlyAcquired()
public void NameCorrectlyAcquired()
{
// Assembling some code
IAssemblyLoader assemblyLoader = new Utils.AsmlDasmlAssemblyLoader(@"
Expand Down Expand Up @@ -51,7 +51,7 @@ class MyClass {
}

[TestMethod]
public void ImplicitObjectCLassInheritanceIsNotGenerated()
public void ImplicitObjectClassInheritanceIsNotGenerated()
{
// Assembling some code
IAssemblyLoader assemblyLoader = new Utils.AsmlDasmlAssemblyLoader(@"
Expand Down Expand Up @@ -79,7 +79,7 @@ class MyClass {
}

[TestMethod]
public void ClassVisibilityCorrectlyAcquired()
public void VisibilityCorrectlyAcquired()
{
// Public
TestVisibility(@"
Expand Down
Loading

0 comments on commit a41f6f9

Please sign in to comment.