Skip to content

Commit

Permalink
Add support for nested classes. +semver: minor (#61)
Browse files Browse the repository at this point in the history
* Add support for nested classes.
* Improves testing for IL generation for Type signatures.
* Resolve indentation problems.
  • Loading branch information
pjbgf authored Aug 19, 2019
1 parent e2f1b24 commit 3871efa
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 14 deletions.
15 changes: 15 additions & 0 deletions src/dotnet-ildasm.Sample/Classes/NestedClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

namespace dotnet_ildasm.Sample.Classes
{
public class ParentClass
{
public class NestedClass {
public string SomeMethod() { return "aaaaa"; }
}

public NestedClass CreateNestedClass() {
return new NestedClass();
}
}
}
48 changes: 42 additions & 6 deletions src/dotnet-ildasm.Tests/IndentationProviderShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ public IndentationProviderShould()
public void Breakline_Before_Specific_Keywords(string inputIL)
{
var indentation = new AutoIndentOutputWriter(_outputWriterDouble);
string expectedIL = $"{Environment.NewLine}{inputIL}";
string expectedIL = $"{Environment.NewLine+Environment.NewLine}{inputIL}";

indentation.Write(inputIL);
var actualIL = _outputWriterDouble.ToString();

Assert.Equal(expectedIL, _outputWriterDouble.ToString());
Assert.Equal(expectedIL, actualIL);
}

[Fact]
Expand All @@ -37,8 +38,9 @@ public void Add_No_Spaces_Outside_Of_Brackets()
var autoIndentWriter = new AutoIndentOutputWriter(_outputWriterDouble);

autoIndentWriter.Write("public static");
var actualIL = _outputWriterDouble.ToString();

Assert.Equal("public static", _outputWriterDouble.ToString());
Assert.Equal("public static", actualIL);
}

[Fact]
Expand All @@ -52,6 +54,28 @@ public void Add_Two_Spaces_Within_First_Open_Brackets()
_outputWriterMock.Received().Write(" .maxstack 8");
}

[Fact]
public void Add_Two_Spaces_For_IL_Statements()
{
var autoIndentWriter = new AutoIndentOutputWriter(_outputWriterMock);

autoIndentWriter.Apply(".method public {");
autoIndentWriter.Apply("IL_0000: nop");

_outputWriterMock.Received().Write(" IL_0000: nop");
}

[Fact]
public void Add_Two_Spaces_For_catch_Statements()
{
var autoIndentWriter = new AutoIndentOutputWriter(_outputWriterMock);

autoIndentWriter.Apply(".method public {");
autoIndentWriter.Apply("catch");

_outputWriterMock.Received().Write(" catch");
}

[Fact]
public void Add_Two_Spaces_In_Same_Line_As_Second_Brackets_Opens()
{
Expand All @@ -64,13 +88,25 @@ public void Add_Two_Spaces_In_Same_Line_As_Second_Brackets_Opens()
autoIndentWriter.Apply(".maxstack 8");

var actualIL = _outputWriterDouble.ToString();
var expectedIL = $"{Environment.NewLine}.class {{{Environment.NewLine} .method public {{ .maxstack 8";
var expectedIL = $"{Environment.NewLine+Environment.NewLine}.class {{{Environment.NewLine+Environment.NewLine} .method public {{ .maxstack 8";

Assert.Equal(expectedIL, actualIL);
}

[Fact]
public void Remove_Spaces_Once_Brackets_Are_Closed()
public void Not_Remove_Spaces_On_Brackets_Closing_Line()
{
var autoIndentWriter = new AutoIndentOutputWriter(_outputWriterMock);

autoIndentWriter.Apply(".class public {");
autoIndentWriter.Apply(".method public {");
autoIndentWriter.Apply("}");

_outputWriterMock.Received().Write(" }");
}

[Fact]
public void Remove_Spaces_After_Brackets_Are_Closed()
{
var autoIndentWriter = new AutoIndentOutputWriter(_outputWriterMock);

Expand Down Expand Up @@ -105,7 +141,7 @@ public void Not_Apply_Indentation_In_Between_Signature_Keywords()
autoIndentWriter.Apply("hidebysig ");

var actualIL = _outputWriterDouble.ToString();
var expectedIL = $"{{{Environment.NewLine} .method public hidebysig ";
var expectedIL = $"{{{Environment.NewLine+Environment.NewLine} .method public hidebysig ";

Assert.Equal(expectedIL, actualIL);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public TypeDefinitionExtensions()
}

[Theory]
#if NETFRAMEWORK
[InlineData("PrivateClass",
".class private auto ansi beforefieldinit dotnet_ildasm.Sample.Classes.PrivateClass extends [System.Runtime]System.Object")]
[InlineData("PublicClass",
Expand All @@ -26,27 +27,63 @@ public TypeDefinitionExtensions()
".class public auto ansi sealed beforefieldinit dotnet_ildasm.Sample.Classes.PublicSealedClass extends [System.Runtime]System.Object")]
[InlineData("PublicAbstractClass",
".class public abstract auto ansi beforefieldinit dotnet_ildasm.Sample.Classes.PublicAbstractClass extends [System.Runtime]System.Object")]
#else
[InlineData("PrivateClass",
".class private auto ansi beforefieldinit dotnet_ildasm.Sample.Classes.PrivateClass extends [netstandard]System.Object")]
[InlineData("PublicClass",
".class public auto ansi beforefieldinit dotnet_ildasm.Sample.Classes.PublicClass extends [netstandard]System.Object")]
[InlineData("PublicSealedClass",
".class public auto ansi sealed beforefieldinit dotnet_ildasm.Sample.Classes.PublicSealedClass extends [netstandard]System.Object")]
[InlineData("PublicAbstractClass",
".class public abstract auto ansi beforefieldinit dotnet_ildasm.Sample.Classes.PublicAbstractClass extends [netstandard]System.Object")]
#endif
[InlineData("DerivedPublicClass",
".class public auto ansi beforefieldinit dotnet_ildasm.Sample.Classes.DerivedPublicClass extends dotnet_ildasm.Sample.Classes.PublicAbstractClass")]
public void Generate_Valid_IL_For_Class_Signatures(string className, string expectedIL)
{
var type = _assemblyDefinition.MainModule.Types.FirstOrDefault(x => x.Name == className);

type.WriteILSignature(_outputWriter);
var actualIL = _outputWriter.ToString();

Assert.Equal(expectedIL, actualIL);
}

Assert.Equal(expectedIL, expectedIL);
[Theory]
#if NETFRAMEWORK
[InlineData("ParentClass", "NestedClass",
".class nested public auto ansi beforefieldinit NestedClass extends [System.Runtime]System.Object")]
#else
[InlineData("ParentClass", "NestedClass",
".class nested public auto ansi beforefieldinit NestedClass extends [netstandard]System.Object")]
#endif
public void Generate_Valid_IL_For_NestedClasses_Signatures(string parentClassName, string nestedClassName, string expectedIL)
{
var parentType = _assemblyDefinition.MainModule.Types.FirstOrDefault(x => x.Name == parentClassName);
var nestedType = parentType.NestedTypes.FirstOrDefault(x => x.Name == nestedClassName);

nestedType.WriteILSignature(_outputWriter);
var actualIL = _outputWriter.ToString();

Assert.Equal(expectedIL, actualIL);
}

[Theory]
#if NETFRAMEWORK
[InlineData("PublicStruct",
".class public sequential ansi sealed beforefieldinit dotnet_ildasm.Sample.Structs.PublicStruct extends [System.Runtime]System.ValueType")]
#else
[InlineData("PublicStruct",
".class public sequential ansi sealed beforefieldinit dotnet_ildasm.Sample.Structs.PublicStruct extends [netstandard]System.ValueType")]
#endif
public void Generate_Valid_IL_For_Struct_Signatures(string structName, string expectedIL)
{
var type = _assemblyDefinition.MainModule.Types.FirstOrDefault(x => x.Name == structName);

type.WriteILSignature(_outputWriter);
var actualIL = _outputWriter.ToString();

Assert.Equal(expectedIL, expectedIL);
Assert.Equal(expectedIL, actualIL);
}
}
}
5 changes: 4 additions & 1 deletion src/dotnet-ildasm/Adapters/AutoIndentOutputWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ public void Apply(string code)
var alreadyUpdatedIndentation = false;

if (IsBreakLineRequired(code))
{
_writer.WriteLine(string.Empty);
_writer.Write(Environment.NewLine);
}

if (code.StartsWith("}"))
{
Expand All @@ -61,7 +64,7 @@ private static bool IsBreakLineRequired(string code)

private static bool IsIndentationRequired(string code)
{
return Regex.IsMatch(code, "^(IL|\\.|//|{){1}",
return Regex.IsMatch(code, "^(catch|IL|\\.|//|{|}){1}",
RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.Singleline);
}

Expand Down
21 changes: 16 additions & 5 deletions src/dotnet-ildasm/Infrastructure/TypeDefinitionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ public static void WriteILSignature(this TypeDefinition typeDefinition, IOutputW
{
outputWriter.Write(".class");

if (typeDefinition.IsPublic)
outputWriter.Write(" public");
else
outputWriter.Write(" private");
if (typeDefinition.IsNested)
{
if (typeDefinition.IsNestedPublic)
outputWriter.Write(" nested public");
if (typeDefinition.IsNestedPrivate)
outputWriter.Write(" nested private");
} else {
if (typeDefinition.IsPublic)
outputWriter.Write(" public");
else
outputWriter.Write(" private");
}

if (typeDefinition.IsSequentialLayout)
outputWriter.Write(" sequential");
Expand All @@ -37,7 +45,10 @@ public static void WriteILSignature(this TypeDefinition typeDefinition, IOutputW
if (typeDefinition.IsBeforeFieldInit)
outputWriter.Write(" beforefieldinit");

outputWriter.Write($" {typeDefinition.FullName}");
if (typeDefinition.IsNested)
outputWriter.Write($" {typeDefinition.Name}");
else
outputWriter.Write($" {typeDefinition.FullName}");

if (typeDefinition.BaseType != null)
outputWriter.Write(
Expand Down
3 changes: 3 additions & 0 deletions src/dotnet-ildasm/TypesProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ private void HandleType(TypeDefinition type)
WriteMethods(type);
WriteCustomAttributes(type);

foreach (var nestedType in type.NestedTypes)
HandleType(nestedType);

_outputWriter.WriteLine($"}} // End of class {type.FullName}");
}

Expand Down

0 comments on commit 3871efa

Please sign in to comment.