diff --git a/src/Generator/Generators/CSharp/CSharpGenerator.cs b/src/Generator/Generators/CSharp/CSharpGenerator.cs index 479eb7f8..bc4a5fb6 100644 --- a/src/Generator/Generators/CSharp/CSharpGenerator.cs +++ b/src/Generator/Generators/CSharp/CSharpGenerator.cs @@ -31,6 +31,7 @@ namespace CppSharp.Generators.CSharp // CheckAbiParameters runs last because hidden structure parameters // should always occur first. + Driver.AddTranslationUnitPass(new MoveOperatorToClassPass()); Driver.AddTranslationUnitPass(new CheckOperatorsOverloadsPass()); Driver.AddTranslationUnitPass(new CheckAbiParameters(Driver.Options)); diff --git a/src/Generator/Passes/MoveOperatorToClassPass.cs b/src/Generator/Passes/MoveOperatorToClassPass.cs new file mode 100644 index 00000000..e63800b5 --- /dev/null +++ b/src/Generator/Passes/MoveOperatorToClassPass.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using CppSharp.AST; + +namespace CppSharp.Passes +{ + public class MoveOperatorToClassPass : TranslationUnitPass + { + public override bool VisitMethodDecl(Method method) + { + return true; + } + + public override bool VisitFunctionDecl(Function function) + { + if (function.Ignore || !function.Name.StartsWith("operator")) + return false; + + string type = function.Parameters[0].Type.Desugar().ToString(); + if (string.IsNullOrEmpty(type)) + return false; + + var @class = Library.FindCompleteClass(type); + if (@class == null) + return false; + + function.ExplicityIgnored = true; + + // Create a new fake method so it acts as a static method. + var method = new Method() + { + Namespace = @class, + OriginalNamespace = function.Namespace, + Name = function.Name, + OriginalName = function.OriginalName, + Mangled = function.Mangled, + Access = AccessSpecifier.Public, + Kind = CXXMethodKind.Operator, + ReturnType = function.ReturnType, + Parameters = new List(function.Parameters), + CallingConvention = function.CallingConvention, + IsVariadic = function.IsVariadic, + IsInline = function.IsInline, + IsStatic = true, + Conversion = MethodConversionKind.FunctionToStaticMethod, + OperatorKind = GetOperatorKind(function.Name) + }; + + @class.Methods.Add(method); + + Console.WriteLine("Static method: {0}::{1}", @class.Name, + function.Name); + + return true; + } + + private static CXXOperatorKind GetOperatorKind(string @operator) + { + const string op = "operator"; + if (!@operator.StartsWith(op)) + { + return CXXOperatorKind.None; + } + switch (@operator.Substring(8).Trim()) + { + case "+": return CXXOperatorKind.Plus; + case "-": return CXXOperatorKind.Minus; + case "!": return CXXOperatorKind.Exclaim; + case "~": return CXXOperatorKind.Tilde; + case "++": return CXXOperatorKind.PlusPlus; + case "--": return CXXOperatorKind.MinusMinus; + case "*": return CXXOperatorKind.Star; + case "/": return CXXOperatorKind.Slash; + case "&": return CXXOperatorKind.Amp; + case "|": return CXXOperatorKind.Pipe; + case "^": return CXXOperatorKind.Caret; + case "<<": return CXXOperatorKind.LessLess; + case ">>": return CXXOperatorKind.GreaterGreater; + case "==": return CXXOperatorKind.EqualEqual; + case "!=": return CXXOperatorKind.ExclaimEqual; + case "<": return CXXOperatorKind.Less; + case ">": return CXXOperatorKind.Greater; + case "<=": return CXXOperatorKind.LessEqual; + case ">=": return CXXOperatorKind.GreaterEqual; + case "+=": return CXXOperatorKind.PlusEqual; + case "-=": return CXXOperatorKind.MinusEqual; + case "*=": return CXXOperatorKind.StarEqual; + case "/=": return CXXOperatorKind.SlashEqual; + case "%=": return CXXOperatorKind.PercentEqual; + case "&=": return CXXOperatorKind.AmpEqual; + case "|=": return CXXOperatorKind.PipeEqual; + case "^=": return CXXOperatorKind.CaretEqual; + case "<<=": return CXXOperatorKind.LessLessEqual; + case ">>=": return CXXOperatorKind.GreaterGreaterEqual; + case "[]": return CXXOperatorKind.Subscript; + case "&&": return CXXOperatorKind.AmpAmp; + case "||": return CXXOperatorKind.PipePipe; + case "=": return CXXOperatorKind.Equal; + case ",": return CXXOperatorKind.Comma; + case "->*": return CXXOperatorKind.ArrowStar; + case "->": return CXXOperatorKind.Arrow; + case "()": return CXXOperatorKind.Call; + case "?": return CXXOperatorKind.Conditional; + case "new": return CXXOperatorKind.New; + case "delete": return CXXOperatorKind.Delete; + case "new[]": return CXXOperatorKind.Array_New; + case "delete[]": return CXXOperatorKind.Array_Delete; + } + return CXXOperatorKind.None; + } + } +}