Skip to content

Commit

Permalink
Major refactoring: refactor GeneratorKind enum into a class (#1794)
Browse files Browse the repository at this point in the history
* Major refactoring: refactor GeneratorKind enum into a class

* Minor fix: add readonly

* Add Type property for GenerationKind + cleanup

* GeneratorKind: add Name property + refactor hardcoded names

* GeneratorKind: add CLIOptions property + refactor hardcoded options

* CppSharp.CLI: minor fix: use generator.ToLower()

* GeneratorKind: fix warning
  • Loading branch information
deadlocklogic authored Nov 13, 2023
1 parent 40f3a09 commit 0edd48c
Show file tree
Hide file tree
Showing 16 changed files with 231 additions and 157 deletions.
30 changes: 5 additions & 25 deletions src/CLI/CLI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,33 +206,13 @@ static void GetFilesFromPath(string path, List<string> errorMessages)

static void GetGeneratorKind(string generator, List<string> errorMessages)
{
switch (generator.ToLower())
foreach (GeneratorKind generatorKind in GeneratorKind.Registered)
{
case "csharp":
options.Kind = GeneratorKind.CSharp;
return;
case "cli":
options.Kind = GeneratorKind.CLI;
return;
case "c":
options.Kind = GeneratorKind.C;
return;
case "cpp":
options.Kind = GeneratorKind.CPlusPlus;
return;
case "napi":
options.Kind = GeneratorKind.NAPI;
return;
case "qjs":
options.Kind = GeneratorKind.QuickJS;
return;
case "ts":
case "typescript":
options.Kind = GeneratorKind.TypeScript;
return;
case "emscripten":
options.Kind = GeneratorKind.Emscripten;
if (generatorKind.IsCLIOptionMatch(generator.ToLower()))
{
options.Kind = generatorKind;
return;
}
}

errorMessages.Add($"Unknown generator kind: {generator}.");
Expand Down
17 changes: 1 addition & 16 deletions src/CLI/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public void Postprocess(Driver driver, ASTContext ctx)
public void Run()
{
var messageBuilder = new StringBuilder();
messageBuilder.Append($"Generating {GetGeneratorKindName(options.Kind)}");
messageBuilder.Append($"Generating {options.Kind.Name}");
messageBuilder.Append($" bindings for {GetPlatformName(options.Platform)} {options.Architecture}");

if (options.Cpp11ABI)
Expand All @@ -225,20 +225,5 @@ private static string GetPlatformName(TargetPlatform? platform)
return platform.ToString();
}
}

private static string GetGeneratorKindName(GeneratorKind kind)
{
switch (kind)
{
case GeneratorKind.CLI:
return "C++/CLI";
case GeneratorKind.CSharp:
return "C#";
case GeneratorKind.NAPI:
return "N-API";
default:
return kind.ToString();
}
}
}
}
8 changes: 6 additions & 2 deletions src/CppParser/Bootstrap/Bootstrap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1778,8 +1778,7 @@ private static string CleanClangNamespaceFromName(string qualifiedName)
return qualifiedName;
}

public static string GetDeclName(Declaration decl,
GeneratorKind kind = GeneratorKind.CPlusPlus)
public static string GetDeclName(Declaration decl, GeneratorKind kind)
{
string name = decl.Name;

Expand Down Expand Up @@ -1811,6 +1810,11 @@ public static string GetDeclName(Declaration decl,
return name;
}

public static string GetDeclName(Declaration decl)
{
return GetDeclName(decl, GeneratorKind.CPlusPlus);
}

public static AST.Type GetDeclType(AST.Type type,
TypePrinter typePrinter)
{
Expand Down
36 changes: 2 additions & 34 deletions src/Generator/Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
using System.Linq;
using CppSharp.AST;
using CppSharp.Generators;
using CppSharp.Generators.C;
using CppSharp.Generators.CLI;
using CppSharp.Generators.Cpp;
using CppSharp.Generators.CSharp;
using CppSharp.Generators.Emscripten;
using CppSharp.Generators.TS;
using CppSharp.Parser;
using CppSharp.Passes;
using CppSharp.Utils;
Expand All @@ -32,31 +26,6 @@ public Driver(DriverOptions options)
ParserOptions = new ParserOptions();
}

Generator CreateGeneratorFromKind(GeneratorKind kind)
{
switch (kind)
{
case GeneratorKind.C:
return new CGenerator(Context);
case GeneratorKind.CPlusPlus:
return new CppGenerator(Context);
case GeneratorKind.CLI:
return new CLIGenerator(Context);
case GeneratorKind.CSharp:
return new CSharpGenerator(Context);
case GeneratorKind.Emscripten:
return new EmscriptenGenerator(Context);
case GeneratorKind.QuickJS:
return new QuickJSGenerator(Context);
case GeneratorKind.NAPI:
return new NAPIGenerator(Context);
case GeneratorKind.TypeScript:
return new TSGenerator(Context);
}

throw new NotImplementedException();
}

void ValidateOptions()
{
if (!Options.Compilation.Platform.HasValue)
Expand Down Expand Up @@ -87,7 +56,7 @@ public void Setup()
ValidateOptions();
ParserOptions.Setup(Platform.Host);
Context = new BindingContext(Options, ParserOptions);
Generator = CreateGeneratorFromKind(Options.GeneratorKind);
Generator = Options.GeneratorKind.CreateGenerator(Context);
}

public void SetupTypeMaps() =>
Expand Down Expand Up @@ -387,8 +356,7 @@ public bool CompileCode(Module module)
out int error, out string errorMessage);
if (error == 0)
{
Diagnostics.Message($@"Compilation succeeded: {
LibraryMappings[module] = Path.Combine(
Diagnostics.Message($@"Compilation succeeded: {LibraryMappings[module] = Path.Combine(
Options.OutputDir, $"{module.LibraryName}.dll")}.");
return true;
}
Expand Down
18 changes: 0 additions & 18 deletions src/Generator/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,6 @@

namespace CppSharp.Generators
{
/// <summary>
/// Kinds of language generators.
/// </summary>
public enum GeneratorKind
{
CLI = 1,
CSharp = 2,
C,
CPlusPlus,
Emscripten,
ObjectiveC,
Java,
Swift,
QuickJS,
NAPI,
TypeScript
}

/// <summary>
/// Output generated by each backend generator.
/// </summary>
Expand Down
151 changes: 151 additions & 0 deletions src/Generator/GeneratorKind.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using CppSharp.AST;
using CppSharp.Generators.C;
using CppSharp.Generators.CLI;
using CppSharp.Generators.Cpp;
using CppSharp.Generators.CSharp;
using CppSharp.Generators.Emscripten;
using CppSharp.Generators.TS;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CppSharp.Generators
{
/// <summary>
/// Kinds of language generators.
/// </summary>
public class GeneratorKind : IEquatable<GeneratorKind>
{
public static readonly HashSet<GeneratorKind> Registered = new();

public string ID { get; }
public string Name { get; }
public System.Type Type { get; }
public string[] CLIOptions { get; }

public GeneratorKind(string id, string name, System.Type type, string[] cLIOptions = null)
{
if (Registered.Any(kind => kind.ID == id))
{
throw new Exception($"GeneratorKind has an already registered ID: {ID}");
}
ID = id;
Name = name;
Type = type;
CLIOptions = cLIOptions;
Registered.Add(this);
}

public Generator CreateGenerator(BindingContext context)
{
return (Generator)Activator.CreateInstance(Type, context);
}

public bool IsCLIOptionMatch(string cliOption)
{
if (CLIOptions == null)
{
return false;
}
return CLIOptions.Any(cliOption.Contains);
}

public static bool operator ==(GeneratorKind obj1, GeneratorKind obj2)
{
if (ReferenceEquals(obj1, obj2))
{
return true;
}
if (obj1 is null)
{
return false;
}
if (obj2 is null)
{
return false;
}
return obj1.Equals(obj2);
}

public static bool operator !=(GeneratorKind obj1, GeneratorKind obj2) => !(obj1 == obj2);

public bool Equals(GeneratorKind other)
{
if (other is null)
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return ID.Equals(other.ID);
}

public override bool Equals(object obj) => Equals(obj as GeneratorKind);

public override int GetHashCode()
{
unchecked
{
return ID.GetHashCode();
}
}

public const string CLI_ID = "CLI";
public static readonly GeneratorKind CLI = new(CLI_ID, "C++/CLI", typeof(CLIGenerator), new[] { "cli" });

public const string CSharp_ID = "CSharp";
public static readonly GeneratorKind CSharp = new(CSharp_ID, "C#", typeof(CSharpGenerator), new[] { "csharp" });

public const string C_ID = "C";
public static readonly GeneratorKind C = new(C_ID, "C", typeof(CGenerator), new[] { "c" });

public const string CPlusPlus_ID = "CPlusPlus";
public static readonly GeneratorKind CPlusPlus = new(CPlusPlus_ID, "CPlusPlus", typeof(CppGenerator), new[] { "cpp" });

public const string Emscripten_ID = "Emscripten";
public static readonly GeneratorKind Emscripten = new(Emscripten_ID, "Emscripten", typeof(EmscriptenGenerator), new[] { "emscripten" });

public const string ObjectiveC_ID = "ObjectiveC";
public static readonly GeneratorKind ObjectiveC = new(ObjectiveC_ID, "ObjectiveC", typeof(NotImplementedGenerator));

public const string Java_ID = "Java";
public static readonly GeneratorKind Java = new(Java_ID, "Java", typeof(NotImplementedGenerator));

public const string Swift_ID = "Swift";
public static readonly GeneratorKind Swift = new(Swift_ID, "Swift", typeof(NotImplementedGenerator));

public const string QuickJS_ID = "QuickJS";
public static readonly GeneratorKind QuickJS = new(QuickJS_ID, "QuickJS", typeof(QuickJSGenerator), new[] { "qjs" });

public const string NAPI_ID = "NAPI";
public static readonly GeneratorKind NAPI = new(NAPI_ID, "N-API", typeof(NAPIGenerator), new[] { "napi" });

public const string TypeScript_ID = "TypeScript";
public static readonly GeneratorKind TypeScript = new(TypeScript_ID, "TypeScript", typeof(TSGenerator), new[] { "ts", "typescript" });
}

public class NotImplementedGenerator : Generator
{
public NotImplementedGenerator(BindingContext context) : base(context)
{
throw new NotImplementedException();
}

public override List<CodeGenerator> Generate(IEnumerable<TranslationUnit> units)
{
throw new NotImplementedException();
}

public override bool SetupPasses()
{
throw new NotImplementedException();
}

protected override string TypePrinterDelegate(CppSharp.AST.Type type)
{
throw new NotImplementedException();
}
}
}
4 changes: 2 additions & 2 deletions src/Generator/Generators/ExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ public static Type GetMappedType(this Type type, TypeMapDatabase typeMaps,

switch (generatorKind)
{
case GeneratorKind.CLI:
case var _ when ReferenceEquals(generatorKind, GeneratorKind.CLI):
return typeMap.CLISignatureType(typePrinterContext).Desugar();
case GeneratorKind.CSharp:
case var _ when ReferenceEquals(generatorKind, GeneratorKind.CSharp):
return typeMap.CSharpSignatureType(typePrinterContext).Desugar();
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/Generator/Passes/CheckDuplicatedNamesPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,22 +202,22 @@ private TypePrinter GetTypePrinter(GeneratorKind kind, BindingContext context)
TypePrinter typePrinter;
switch (kind)
{
case GeneratorKind.C:
case var _ when ReferenceEquals(kind, GeneratorKind.C):
typePrinter = new CppTypePrinter(Context) { PrintFlavorKind = CppTypePrintFlavorKind.C };
break;
case GeneratorKind.Emscripten:
case var _ when ReferenceEquals(kind, GeneratorKind.Emscripten):
typePrinter = new EmscriptenTypePrinter(Context);
break;;
case GeneratorKind.CPlusPlus:
case GeneratorKind.QuickJS:
case GeneratorKind.NAPI:
case GeneratorKind.TypeScript:
case var _ when ReferenceEquals(kind, GeneratorKind.CPlusPlus):
case var _ when ReferenceEquals(kind, GeneratorKind.QuickJS):
case var _ when ReferenceEquals(kind, GeneratorKind.NAPI):
case var _ when ReferenceEquals(kind, GeneratorKind.TypeScript):
typePrinter = new CppTypePrinter(Context);
break;
case GeneratorKind.CLI:
case var _ when ReferenceEquals(kind, GeneratorKind.CLI):
typePrinter = new CLITypePrinter(Context);
break;
case GeneratorKind.CSharp:
case var _ when ReferenceEquals(kind, GeneratorKind.CSharp):
typePrinter = new CSharpTypePrinter(Context);
break;
default:
Expand Down
7 changes: 4 additions & 3 deletions src/Generator/Passes/ValidateOperatorsPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,12 @@ private bool IsValidOperatorOverload(Method @operator)
{
Parameter parameter = @operator.Parameters.Last();
Type type = parameter.Type.Desugar();
switch (Options.GeneratorKind)
var kind = Options.GeneratorKind;
switch (kind)
{
case GeneratorKind.CLI:
case var _ when ReferenceEquals(kind, GeneratorKind.CLI):
return type.IsPrimitiveType(PrimitiveType.Int);
case GeneratorKind.CSharp:
case var _ when ReferenceEquals(kind, GeneratorKind.CSharp):
Types.TypeMap typeMap;
if (Context.TypeMaps.FindTypeMap(type, out typeMap))
{
Expand Down
2 changes: 1 addition & 1 deletion src/Generator/Types/DeclMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class DeclMapAttribute : Attribute
{
public GeneratorKind GeneratorKind { get; set; }

public DeclMapAttribute() : this(0)
public DeclMapAttribute()
{
}

Expand Down
Loading

1 comment on commit 0edd48c

@tritao
Copy link
Collaborator

@tritao tritao commented on 0edd48c Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a minor regression: Generating bindings for CSharp (CppSharp.Generators.GeneratorKind)

Looks like GeneratorKind.ToString might need to be implemented.

Please sign in to comment.