| 
3 | 3 | 
 
  | 
4 | 4 | namespace CppSharp.Passes  | 
5 | 5 | {  | 
6 |  | -    /// <summary>  | 
7 |  | -    /// Moves a function to a class, if any, named after the function's header.  | 
8 |  | -    /// </summary>  | 
9 | 6 |     public class MoveFunctionToClassPass : TranslationUnitPass  | 
10 | 7 |     {  | 
 | 8 | +        public MoveFunctionToClassPass()  | 
 | 9 | +        {  | 
 | 10 | +            VisitOptions.VisitClassBases = VisitOptions.VisitClassFields =  | 
 | 11 | +            VisitOptions.VisitClassMethods = VisitOptions.VisitClassProperties =  | 
 | 12 | +            VisitOptions.VisitClassTemplateSpecializations = VisitOptions.VisitEventParameters =  | 
 | 13 | +            VisitOptions.VisitFunctionParameters = VisitOptions.VisitFunctionReturnType =  | 
 | 14 | +            VisitOptions.VisitNamespaceEnums = VisitOptions.VisitNamespaceEvents =  | 
 | 15 | +            VisitOptions.VisitNamespaceTemplates = VisitOptions.VisitNamespaceTypedefs =  | 
 | 16 | +            VisitOptions.VisitNamespaceVariables = VisitOptions.VisitPropertyAccessors =  | 
 | 17 | +            VisitOptions.VisitTemplateArguments = false;  | 
 | 18 | +        }  | 
 | 19 | + | 
11 | 20 |         public override bool VisitFunctionDecl(Function function)  | 
12 | 21 |         {  | 
13 |  | -            if (!VisitDeclaration(function))  | 
 | 22 | +            if (!function.IsGenerated)  | 
14 | 23 |                 return false;  | 
15 | 24 | 
 
  | 
16 |  | -            if (!function.IsGenerated || function.Namespace is Class)  | 
 | 25 | +            Class @class = FindClassToMoveFunctionTo(function);  | 
 | 26 | + | 
 | 27 | +            if (@class == null ||  | 
 | 28 | +                @class.TranslationUnit.Module != function.TranslationUnit.Module)  | 
17 | 29 |                 return false;  | 
18 | 30 | 
 
  | 
19 |  | -            var @class = FindClassToMoveFunctionTo(function.Namespace);  | 
20 |  | -            if (@class != null && @class.TranslationUnit.Module == function.TranslationUnit.Module)  | 
 | 31 | +            // Create a new fake method so it acts as a static method.  | 
 | 32 | +            var method = new Method(function)  | 
 | 33 | +            {  | 
 | 34 | +                Namespace = @class,  | 
 | 35 | +                OperatorKind = function.OperatorKind,  | 
 | 36 | +                OriginalFunction = null,  | 
 | 37 | +                IsStatic = true  | 
 | 38 | +            };  | 
 | 39 | +            if (method.IsOperator)  | 
21 | 40 |             {  | 
22 |  | -                MoveFunction(function, @class);  | 
23 |  | -                Diagnostics.Debug("Function moved to class: {0}::{1}", @class.Name, function.Name);  | 
 | 41 | +                method.IsNonMemberOperator = true;  | 
 | 42 | +                method.Kind = CXXMethodKind.Operator;  | 
24 | 43 |             }  | 
25 | 44 | 
 
  | 
26 |  | -            if (function.IsOperator)  | 
27 |  | -                function.ExplicitlyIgnore();  | 
 | 45 | +            function.ExplicitlyIgnore();  | 
 | 46 | + | 
 | 47 | +            @class.Methods.Add(method);  | 
 | 48 | + | 
 | 49 | +            Diagnostics.Debug($"Function {function.Name} moved to class {@class.Name}");  | 
28 | 50 | 
 
  | 
29 | 51 |             return true;  | 
30 | 52 |         }  | 
31 | 53 | 
 
  | 
32 |  | -        private Class FindClassToMoveFunctionTo(INamedDecl @namespace)  | 
 | 54 | +        private Class FindClassToMoveFunctionTo(Function function)  | 
33 | 55 |         {  | 
34 |  | -            var unit = @namespace as TranslationUnit;  | 
35 |  | -            if (unit == null)  | 
 | 56 | +            Class @class = null;  | 
 | 57 | +            if (function.IsOperator)  | 
36 | 58 |             {  | 
37 |  | -                return ASTContext.FindClass(  | 
38 |  | -                    @namespace.Name, ignoreCase: true).FirstOrDefault();  | 
 | 59 | +                foreach (var param in function.Parameters)  | 
 | 60 | +                {  | 
 | 61 | +                    if (FunctionToInstanceMethodPass.GetClassParameter(param, out @class))  | 
 | 62 | +                        break;  | 
 | 63 | +                }  | 
 | 64 | +                if (@class == null)  | 
 | 65 | +                    function.ExplicitlyIgnore();  | 
39 | 66 |             }  | 
40 |  | -            return ASTContext.FindCompleteClass(  | 
41 |  | -                unit.FileNameWithoutExtension.ToLowerInvariant(), true);  | 
42 |  | -        }  | 
43 |  | - | 
44 |  | -        private static void MoveFunction(Function function, Class @class)  | 
45 |  | -        {  | 
46 |  | -            var method = new Method(function)  | 
 | 67 | +            else  | 
47 | 68 |             {  | 
48 |  | -                Namespace = @class,  | 
49 |  | -                IsStatic = true  | 
50 |  | -            };  | 
51 |  | - | 
52 |  | -            function.ExplicitlyIgnore();  | 
53 |  | - | 
54 |  | -            if (method.OperatorKind != CXXOperatorKind.None)  | 
55 |  | -            {  | 
56 |  | -                var param = function.Parameters[0];  | 
57 |  | -                Class type;  | 
58 |  | -                if (!FunctionToInstanceMethodPass.GetClassParameter(param, out type))  | 
59 |  | -                    return;  | 
60 |  | -                method.Kind = CXXMethodKind.Operator;  | 
61 |  | -                method.IsNonMemberOperator = true;  | 
62 |  | -                method.OriginalFunction = null;  | 
 | 69 | +                var unit = function.Namespace as TranslationUnit;  | 
 | 70 | +                @class = unit == null  | 
 | 71 | +                    ? ASTContext.FindClass(  | 
 | 72 | +                        function.Namespace.Name, ignoreCase: true).FirstOrDefault()  | 
 | 73 | +                    : ASTContext.FindCompleteClass(  | 
 | 74 | +                        unit.FileNameWithoutExtension.ToLowerInvariant(), true);  | 
63 | 75 |             }  | 
64 | 76 | 
 
  | 
65 |  | -            @class.Methods.Add(method);  | 
 | 77 | +            return @class;  | 
66 | 78 |         }  | 
67 | 79 |     }  | 
68 | 80 | }  | 
0 commit comments