Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions TestTransformer/SimpleTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using Platform.RegularExpressions.Transformer.CSharpToCpp;

class SimpleTest
{
static void Main(string[] args)
{
var transformer = new CSharpToCppTransformer();

// Test simple interface
string simpleInterface = @"interface ISimple
{
void Method();
}";

Console.WriteLine("=== SIMPLE INTERFACE TEST ===");
Console.WriteLine("Input:");
Console.WriteLine(simpleInterface);
Console.WriteLine("\nOutput:");
Console.WriteLine(transformer.Transform(simpleInterface));

// Test templated interface
string templatedInterface = @"interface ITest<T>
{
void Method(T value);
}";

Console.WriteLine("\n=== TEMPLATED INTERFACE TEST ===");
Console.WriteLine("Input:");
Console.WriteLine(templatedInterface);
Console.WriteLine("\nOutput:");
Console.WriteLine(transformer.Transform(templatedInterface));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,127 @@ public static void Main(string[] args)
var actualResult = transformer.Transform(helloWorldCode);
Assert.Equal(expectedResult, actualResult);
}

[Fact]
public void PragmaOncePreservationTest()
{
const string input = @"#pragma once
using System;

class Test
{
public void Method() { }
}";
const string expectedResult = @"#pragma once

class Test
{
public: void Method() { }
};";
var transformer = new CSharpToCppTransformer();
var actualResult = transformer.Transform(input);
Assert.Equal(expectedResult, actualResult);
}

[Fact]
public void PragmaWarningRemovalTest()
{
const string input = @"#pragma warning disable CS1591
using System;

class Test
{
public void Method() { }
}";
const string expectedResult = @"class Test
{
public: void Method() { }
};";
var transformer = new CSharpToCppTransformer();
var actualResult = transformer.Transform(input);
Assert.Equal(expectedResult, actualResult);
}

[Fact]
public void SimpleInterfaceToStructTest()
{
const string input = @"
interface ITest
{
void Method();
}";
const string expectedResult = @"
struct ITest
{
public:
virtual void Method() = 0;
virtual ~ITest() = default;
};";
var transformer = new CSharpToCppTransformer();
var actualResult = transformer.Transform(input);
Assert.Equal(expectedResult, actualResult);
}

[Fact]
public void TemplatedInterfaceToStructTest()
{
const string input = @"
interface ITest<T>
{
void Method(T value);
}";
const string expectedResult = @"
template <typename ...> struct ITest;
template <typename T>
struct ITest<T>
{
public:
virtual void Method(T value) = 0;
virtual ~ITest() = default;
};";
var transformer = new CSharpToCppTransformer();
var actualResult = transformer.Transform(input);
Assert.Equal(expectedResult, actualResult);
}

[Fact]
public void TemplatedClassSeparationTest()
{
const string input = @"
class TestClass<T>
{
public T Value { get; set; }
}";
const string expectedResult = @"
template <typename ...> class TestClass;
template <typename T>
class TestClass<T>
{
public: inline T Value;
};";
var transformer = new CSharpToCppTransformer();
var actualResult = transformer.Transform(input);
Assert.Equal(expectedResult, actualResult);
}

[Fact]
public void TemplatedStructSeparationTest()
{
const string input = @"
struct TestStruct<T>
{
public T Value { get; set; }
}";
const string expectedResult = @"
template <typename ...> struct TestStruct;
template <typename T>
struct TestStruct<T>
{
public: inline T Value;
};";
var transformer = new CSharpToCppTransformer();
var actualResult = transformer.Transform(input);
Assert.Equal(expectedResult, actualResult);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class CSharpToCppTransformer : TextTransformer
(new Regex(@"(\r?\n)?[ \t]+//+.+"), "", 0),
// #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
//
(new Regex(@"^\s*?\#pragma[\sa-zA-Z0-9]+$"), "", 0),
(new Regex(@"^\s*?\#pragma(?! once)[\sa-zA-Z0-9]+$"), "", 0),
// {\n\n\n
// {
(new Regex(@"{\s+[\r\n]+"), "{" + Environment.NewLine, 0),
Expand Down Expand Up @@ -86,14 +86,14 @@ public class CSharpToCppTransformer : TextTransformer
// class
(new Regex(@"((public|protected|private|internal|abstract|static) )*(?<category>interface|class|struct)"), "${category}", 0),
// class GenericCollectionMethodsBase<TElement> {
// template <typename TElement> class GenericCollectionMethodsBase {
(new Regex(@"(?<before>\r?\n)(?<indent>[ \t]*)(?<type>class|struct) (?<typeName>[a-zA-Z0-9]+)<(?<typeParameters>[a-zA-Z0-9 ,]+)>(?<typeDefinitionEnding>[^{]+){"), "${before}${indent}template <typename ...> ${type} ${typeName};" + Environment.NewLine + "${indent}template <typename ${typeParameters}> ${type} ${typeName}<${typeParameters}>${typeDefinitionEnding}{", 0),
// template <typename TElement>\nclass GenericCollectionMethodsBase {
(new Regex(@"(?<before>\r?\n)(?<indent>[ \t]*)(?<type>class|struct) (?<typeName>[a-zA-Z0-9]+)<(?<typeParameters>[a-zA-Z0-9 ,]+)>(?<typeDefinitionEnding>[^{]+){"), "${before}${indent}template <typename ...> ${type} ${typeName};" + Environment.NewLine + "${indent}template <typename ${typeParameters}>" + Environment.NewLine + "${indent}${type} ${typeName}<${typeParameters}>${typeDefinitionEnding}{", 0),
// static void TestMultipleCreationsAndDeletions<TElement>(SizedBinaryTreeMethodsBase<TElement> tree, TElement* root)
// template<typename T> static void TestMultipleCreationsAndDeletions<TElement>(SizedBinaryTreeMethodsBase<TElement> tree, TElement* root)
(new Regex(@"static ([a-zA-Z0-9]+) ([a-zA-Z0-9]+)<([a-zA-Z0-9]+)>\(([^\)\r\n]+)\)"), "template <typename $3> static $1 $2($4)", 0),
// interface IFactory<out TProduct> {
// template <typename...> class IFactory;\ntemplate <typename TProduct> class IFactory<TProduct>
(new Regex(@"(?<before>\r?\n)(?<indent>[ \t]*)interface (?<interface>[a-zA-Z0-9]+)<(?<typeParameters>[a-zA-Z0-9 ,]+)>(?<typeDefinitionEnding>[^{]+){"), "${before}${indent}template <typename ...> class ${interface};" + Environment.NewLine + "${indent}template <typename ${typeParameters}> class ${interface}<${typeParameters}>${typeDefinitionEnding}{" + Environment.NewLine + " public:", 0),
// template <typename...> struct IFactory;\ntemplate <typename TProduct>\nstruct IFactory<TProduct>
(new Regex(@"(?<before>\r?\n)(?<indent>[ \t]*)interface (?<interface>[a-zA-Z0-9]+)<(?<typeParameters>[a-zA-Z0-9 ,]+)>(?<typeDefinitionEnding>[^{]+){"), "${before}${indent}template <typename ...> struct ${interface};" + Environment.NewLine + "${indent}template <typename ${typeParameters}>" + Environment.NewLine + "${indent}struct ${interface}<${typeParameters}>${typeDefinitionEnding}{" + Environment.NewLine + " public:", 0),
// template <typename TObject, TProperty, TValue>
// template <typename TObject, typename TProperty, typename TValue>
(new Regex(@"(?<before>template <((, )?typename [a-zA-Z0-9]+)+, )(?<typeParameter>[a-zA-Z0-9]+)(?<after>(,|>))"), "${before}typename ${typeParameter}${after}", 10),
Expand Down Expand Up @@ -279,8 +279,12 @@ public class CSharpToCppTransformer : TextTransformer
// class IProperty : public ISetter<TValue, TObject>, public IProvider<TValue, TObject>
(new Regex(@"(?<before>(interface|struct|class) [a-zA-Z_]\w* : ((public [a-zA-Z_][\w:]*(<[a-zA-Z0-9 ,]+>)?, )+)?)(?<inheritedType>(?!public)[a-zA-Z_][\w:]*(<[a-zA-Z0-9 ,]+>)?)(?<after>(, [a-zA-Z_][\w:]*(?!>)|[ \r\n]+))"), "${before}public ${inheritedType}${after}", 10),
// interface IDisposable {
// class IDisposable { public:
(new Regex(@"(?<before>\r?\n)(?<indent>[ \t]*)interface (?<interface>[a-zA-Z_]\w*)(?<typeDefinitionEnding>[^{]+){"), "${before}${indent}class ${interface}${typeDefinitionEnding}{" + Environment.NewLine + " public:", 0),
// struct IDisposable { public:
(new Regex(@"(?<before>\r?\n)(?<indent>[ \t]*)interface (?<interface>[a-zA-Z_]\w*)(?<typeDefinitionEnding>[^{]+){"), "${before}${indent}struct ${interface}${typeDefinitionEnding}{" + Environment.NewLine + " public:", 0),
// Add virtual destructors for structs (originally interfaces) that contain virtual methods
// struct ITest<T> { public: virtual void Method(T value) = 0; }
// struct ITest<T> { public: virtual void Method(T value) = 0; virtual ~ITest() = default; }
(new Regex(@"(?<beforeEnd>struct (?<structName>[a-zA-Z_][a-zA-Z0-9_]*)[^{]*\{[^}]*public:[^}]*virtual[^}]*?(?=\r?\n[ \t]*}))(?<endIndent>\r?\n[ \t]*)(?<end>})"), "${beforeEnd}${endIndent} virtual ~${structName}() = default;${endIndent}${end}", 0),
// struct TreeElement { }
// struct TreeElement { };
(new Regex(@"(struct|class) ([a-zA-Z0-9]+)(\s+){([\sa-zA-Z0-9;:_]+?)}([^;])"), "$1 $2$3{$4};$5", 0),
Expand Down Expand Up @@ -752,6 +756,11 @@ public class CSharpToCppTransformer : TextTransformer
// \n\n}
// \n}
(new Regex(@"\r?\n[ \t]*\r?\n(?<end>[ \t]*})"), Environment.NewLine + "${end}", 10),
// Fix virtual destructors to use = default instead of = 0 (FINAL STAGE)
// Only applies to destructors that were already added (i.e. interfaces converted to structs)
// virtual ~ITest() = 0;
// virtual ~ITest() = default;
(new Regex(@"(\s*)virtual ~([a-zA-Z_][a-zA-Z0-9_]*)\(\) = 0;"), "$1virtual ~$2() = default;", 0),
}.Cast<ISubstitutionRule>().ToList();

/// <summary>
Expand Down
65 changes: 65 additions & 0 deletions examples/TestTransformer/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using Platform.RegularExpressions.Transformer.CSharpToCpp;

class TestTransformer
{
static void Main(string[] args)
{
var transformer = new CSharpToCppTransformer();

// Test pragma once
string pragmaTest = @"#pragma once
using System;

class Test
{
public void Method() { }
}";

Console.WriteLine("=== PRAGMA ONCE TEST ===");
Console.WriteLine("Input:");
Console.WriteLine(pragmaTest);
Console.WriteLine("\nOutput:");
Console.WriteLine(transformer.Transform(pragmaTest));

// Test simple interface
string simpleInterface = @"
interface ITest
{
void Method();
}";

Console.WriteLine("\n=== SIMPLE INTERFACE TEST ===");
Console.WriteLine("Input:");
Console.WriteLine(simpleInterface);
Console.WriteLine("\nOutput:");
var simpleOutput = transformer.Transform(simpleInterface);
Console.WriteLine(simpleOutput);

// Test templated interface
string interfaceTest = @"
interface ITest<T>
{
void Method(T value);
}";

Console.WriteLine("\n=== TEMPLATED INTERFACE TEST ===");
Console.WriteLine("Input:");
Console.WriteLine(interfaceTest);
Console.WriteLine("\nOutput:");
Console.WriteLine(transformer.Transform(interfaceTest));

// Test struct
string structTest = @"struct TestStruct<T>
{
public T Value { get; set; }
public void Method() { }
}";

Console.WriteLine("\n=== STRUCT TEST ===");
Console.WriteLine("Input:");
Console.WriteLine(structTest);
Console.WriteLine("\nOutput:");
Console.WriteLine(transformer.Transform(structTest));
}
}
14 changes: 14 additions & 0 deletions examples/TestTransformer/TestTransformer.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../../csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/Platform.RegularExpressions.Transformer.CSharpToCpp.csproj" />
</ItemGroup>

</Project>
43 changes: 43 additions & 0 deletions examples/current_behavior.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
=== PRAGMA ONCE TEST ===
Input:
#pragma once
using System;

class Test
{
public void Method() { }
}

Output:
class Test
{
public: void Method() { }
};

=== INTERFACE TEST ===
Input:
interface ITest<T>
{
void Method(T value);
}

Output:
interface ITest<T>
{
virtual void Method(T value) = 0;
}

=== STRUCT TEST ===
Input:
struct TestStruct<T>
{
public T Value { get; set; }
public void Method() { }
}

Output:
struct TestStruct<T>
{
public: inline T Value;
public: void Method() { }
};
Empty file.
4 changes: 4 additions & 0 deletions examples/debug_destructor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface ITest
{
void Method();
}
Loading
Loading