示例#1
0
        private void GenerateWrapperClassConstructors(NodeJSTypeReference classToWrapTypeReference)
        {
            Class classToWrap = classToWrapTypeReference.Declaration as Class;

            string classNameWrap          = NamingHelper.GenerateClassWrapName(classToWrap.Name);
            string classNameWrapperMember = NamingHelper.GenerateClassWrapperMember(classToWrap.Name);

            IEnumerable <Method> constructors = classToWrap.Constructors.OrderByDescending(s => s.Parameters.Count);

            // Supported implementations comment
            PushBlock(BlockKind.Method);
            WriteLine("// Supported implementations");
            foreach (Method constructor in constructors.OrderBy(s => s.Parameters.Count))
            {
                WriteLine("// {0}({1})", classToWrap.Name, nodeJSTypePrinter.VisitParameters(constructor.Parameters, true));
            }

            // Constructor for wrapped class
            WriteLine("{0}::{0}(Nan::NAN_METHOD_ARGS_TYPE info)", classNameWrap);
            WriteLine("  : {0}(NULL)", classNameWrapperMember);
            WriteStartBraceIndent();

            bool firstConstructorCreated = false;

            // Generate check for constructor arguments
            WriteLine("// Check constructor arguments");
            foreach (Method constructor in constructors.OrderBy(s => s.Parameters.Count))
            {
                // Generate other constructors than default
                string generatedCheckStatement = (firstConstructorCreated ? "else " : string.Empty);
                generatedCheckStatement += "if " + nodeJSTypeCheckPrinter.GenerateCheckStatement(constructor.Parameters);

                // Output arguments checker
                WriteLine(generatedCheckStatement);
                WriteStartBraceIndent();

                // Generate wrapper for parameter arguments
                string generatedArgumentsWrapped = nodeJSTypePrinter.GenerateParameterWrapper(this, constructor.Parameters);

                // Generate construction of wrapped member
                PushBlock(BlockKind.MethodBody);
                WriteLine("// {0}({1})", classToWrap.Name, nodeJSTypePrinter.VisitParameters(constructor.Parameters, true));
                WriteLine("{0} = new {1}({2});", classNameWrapperMember, classToWrap.Name, generatedArgumentsWrapped);
                PopBlock(NewLineKind.Never);
                WriteCloseBraceIndent();

                // Remember that we have created an constructor
                firstConstructorCreated = true;
            }

            WriteCloseBraceIndent();
            PopBlock(NewLineKind.BeforeNextBlock);
        }
示例#2
0
        private void GenerateInclude(ASTRecord <Declaration> record)
        {
            var decl = record.Value;

            if (decl.Namespace == null)
            {
                return;
            }

            // Find a type map for the declaration and use it if it exists.
            CppSharp.Types.TypeMap typeMap;
            if (TypeMapDatabase.FindTypeMap(record.Value, out typeMap))
            {
                (typeMap as TypeMap).Declaration = record.Value;
                (typeMap as TypeMap).NodeJSTypeReference(this, record);

                return;
            }

            TranslationUnit translationUnit = decl.Namespace.TranslationUnit;

            if (translationUnit.IsSystemHeader)
            {
                return;
            }

            if (!decl.IsGenerated)
            {
                return;
            }

            if (IsBuiltinTypedef(decl))
            {
                return;
            }

            NodeJSTypeReference typeRef = GetTypeReference(decl);

            if (typeRef.Include.TranslationUnit == null)
            {
                typeRef.Include = new Include
                {
                    Type            = translationUnit.IsGenerated ? Include.IncludeType.Quoted : Include.IncludeType.Angled,
                    File            = GetIncludePath(translationUnit),
                    TranslationUnit = translationUnit
                };
            }

            typeRef.Include.InHeader |= IsIncludeInHeader(record);
        }
示例#3
0
        private void GenerateWrapperClassDestructors(NodeJSTypeReference classToWrapTypeReference)
        {
            Class  classToWrap            = classToWrapTypeReference.Declaration as Class;
            string classNameWrap          = NamingHelper.GenerateClassWrapName(classToWrap.Name);
            string classNameWrapperMember = NamingHelper.GenerateClassWrapperMember(classToWrap.Name);

            // Destructor for wrapped class
            PushBlock(BlockKind.Method);
            WriteLine("{0}::~{0}()", classNameWrap);
            WriteStartBraceIndent();
            WriteLine("delete {0};", classNameWrapperMember);
            WriteCloseBraceIndent();
            PopBlock(NewLineKind.BeforeNextBlock);
        }
示例#4
0
        public NodeJSTypeReference GetTypeReference(Declaration decl)
        {
            if (typeReferences.ContainsKey(decl))
            {
                return(typeReferences[decl]);
            }

            NodeJSTypeReference reference = new NodeJSTypeReference {
                Declaration = decl
            };

            typeReferences.Add(decl, reference);

            return(reference);
        }
示例#5
0
        private void GenerateNestedIncludeImplementations()
        {
            NodeJSTypeReferenceCollector typeReferenceCollector = new NodeJSTypeReferenceCollector(Context.ConfigurationContext, Context.TypeMaps, Context.Options);

            typeReferenceCollector.Process(TranslationUnit);

            // Find own class to wrap
            NodeJSTypeReference classToWrapTypeReference = typeReferenceCollector.TypeReferences
                                                           .Where(item => item.Declaration is Class)
                                                           .Where(item => NamingHelper.GenerateTrimmedClassName(TranslationUnit.FileNameWithoutExtension).ToLower().Equals(NamingHelper.GenerateTrimmedClassName(item.Declaration.Name).ToLower()))
                                                           .FirstOrDefault();

            string className     = string.Empty;
            string classNameWrap = string.Empty;

            // Generate wrapper class name
            if (classToWrapTypeReference != null)
            {
                className     = nodeJSTypePrinter.VisitDeclaration(classToWrapTypeReference.Declaration);
                classNameWrap = NamingHelper.GenerateClassWrapName(className);
            }
            else
            {
                TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
                classNameWrap = NamingHelper.GenerateClassWrapName(textInfo.ToTitleCase(TranslationUnit.FileNameWithoutExtension));
            }

            // Generate nested class initialize
            IEnumerable <string> nestedIncludes = GetNestedIncludes(classNameWrap);

            if (nestedIncludes.Count() > 0)
            {
                foreach (string include in nestedIncludes)
                {
                    //string includeId = string.IsNullOrEmpty(include.Alias) ? include.Id : include.Alias.ToLower();
                    WriteLine("#include \"{0}/{1}.h\"", TranslationUnit.FileNameWithoutExtension.ToLower(), include);
                }
            }
        }
示例#6
0
        private void GenerateWrapperClassImplementations()
        {
            NodeJSTypeReferenceCollector typeReferenceCollector = new NodeJSTypeReferenceCollector(Context.ConfigurationContext, Context.TypeMaps, Context.Options);

            typeReferenceCollector.Process(TranslationUnit);

            NodeJSTypeReference classToWrapTypeReference = typeReferenceCollector.TypeReferences
                                                           .Where(item => item.Declaration is Class)
                                                           .Where(item => NamingHelper.GenerateTrimmedClassName(TranslationUnit.FileNameWithoutExtension).ToLower().Equals(NamingHelper.GenerateTrimmedClassName(item.Declaration.Name).ToLower()))
                                                           .FirstOrDefault();

            string className     = string.Empty;
            string classNameWrap = string.Empty;

            // Generate wrapper class name
            if (classToWrapTypeReference != null)
            {
                className     = nodeJSTypePrinter.VisitDeclaration(classToWrapTypeReference.Declaration);
                classNameWrap = NamingHelper.GenerateClassWrapName(className);
            }
            else
            {
                TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
                classNameWrap = textInfo.ToTitleCase(TranslationUnit.FileNameWithoutExtension) + "Wrap";
            }

            // Check if we need constructor & destructor
            if (classToWrapTypeReference != null)
            {
                // Generate NodeJS wrapper prototypes
                GenerateWrapperClassPersistentFunctions(classNameWrap);

                // Generate constructors
                GenerateWrapperClassConstructors(classToWrapTypeReference);
                GenerateWrapperClassDestructors(classToWrapTypeReference);

                // TODO: New Instance & New
            }

            // Generate initialize
            GenerateWrapperInitialize(classToWrapTypeReference, classNameWrap, typeReferenceCollector);

            // Check if we need to generate methods
            if (methodsProcessed.Count > 0)
            {
                GenerateWrapperMethods(classToWrapTypeReference, classNameWrap, typeReferenceCollector);
            }

            // Check if we need to generate functions
            if (functionsProcessed.Count > 0)
            {
                GenerateWrapperFunctions(classNameWrap, typeReferenceCollector);
            }

            // Check if translation unit is an module
            if (Context.ConfigurationContext.ConfigFilesLoaded.Where(config => ((config.Module != null) && (config.Module == TranslationUnit.FileNameWithoutExtension))).Count() > 0)
            {
                // Generate Node JS initialize for specified module
                PushBlock(BlockKind.Footer);
                WriteLine("NODE_MODULE({0}, {1}::Initialize)", TranslationUnit.FileNameWithoutExtension, classNameWrap);
                PopBlock(NewLineKind.BeforeNextBlock);
            }
        }
示例#7
0
        private void GenerateWrapperInitialize(NodeJSTypeReference classToWrapTypeReference, string classNameWrap, NodeJSTypeReferenceCollector typeReferenceCollector)
        {
            PushBlock(BlockKind.Method);
            WriteLine("NAN_MODULE_INIT({0}::Initialize)", classNameWrap);
            WriteStartBraceIndent();

            // Generate constructor template code
            if (classToWrapTypeReference != null)
            {
                // Find class to wrap
                Class classToWrap = classToWrapTypeReference.Declaration as Class;

                PushBlock(BlockKind.MethodBody);
                WriteLine("// Prepare constructor template");
                WriteLine("Local <FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);");
                WriteLine("tpl->SetClassName(Nan::New(\"{0}\").ToLocalChecked());", classNameWrap);
                WriteLine("tpl->InstanceTemplate()->SetInternalFieldCount(1);");
                PopBlock(NewLineKind.BeforeNextBlock);

                // Generate methods prototypes
                PushBlock(BlockKind.MethodBody);
                WriteLine("// Register prototypes to template");

                foreach (Method method in classToWrap.Methods)
                {
                    // Skip constructors
                    if (method.IsConstructor)
                    {
                        continue;
                    }

                    // Skip on other access level than public
                    if (method.Access != AccessSpecifier.Public)
                    {
                        continue;
                    }

                    // Process method only once
                    if (methodsProcessed.Contains(method.Name))
                    {
                        continue;
                    }

                    // Output method declaration
                    string methodNameNorm  = method.Name;
                    string methodNameLower = methodNameNorm.Substring(0, 1).ToLower() + methodNameNorm.Substring(1);
                    WriteLine("Nan::SetPrototypeMethod(tpl, \"{0}\", {1});", methodNameLower, methodNameNorm);
                    methodsProcessed.Add(method.Name);
                }

                PopBlock(NewLineKind.BeforeNextBlock);

                PushBlock(BlockKind.MethodBody);
                WriteLine("// Register template in Node JS");
                WriteLine("prototype.Reset(tpl);");
                WriteLine("Local<Function> function = Nan::GetFunction(tpl).ToLocalChecked();");
                WriteLine("constructor.Reset(function);");
                WriteLine("Nan::Set(target, Nan::New(\"{0}\").ToLocalChecked(), function);", classToWrap.Name);
                PopBlock(NewLineKind.BeforeNextBlock);
            }

            // Find static functions
            List <Function> functions = typeReferenceCollector.TypeReferences
                                        .Where(item => ((item.Declaration is Function) && !(item.Declaration is Method)))
                                        .Select(item => item.Declaration as Function).ToList();

            // Generate static methods
            if (functions.Count > 0)
            {
                PushBlock(BlockKind.MethodBody);
                WriteLine("// Register static functions in Node JS");

                foreach (Function function in functions)
                {
                    // Skip on other access level than public
                    if (function.Access != AccessSpecifier.Public)
                    {
                        continue;
                    }

                    // Process method only once
                    if (functionsProcessed.Contains(function.Name))
                    {
                        continue;
                    }

                    // Output function declaration
                    string functionNameNorm  = function.Name;
                    string functionNameLower = functionNameNorm.Substring(0, 1).ToLower() + functionNameNorm.Substring(1);
                    WriteLine("Nan::Set(target, Nan::New<String>(\"{0}\").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>({1}::{2})).ToLocalChecked());", functionNameLower, classNameWrap, functionNameNorm);
                    functionsProcessed.Add(function.Name);
                }

                PopBlock(NewLineKind.BeforeNextBlock);
            }

            // Generate nested class initialize
            IEnumerable <string> nestedIncludes = GetNestedIncludes(classNameWrap);

            if (nestedIncludes.Count() > 0)
            {
                PushBlock(BlockKind.MethodBody);
                WriteLine("// Initialize dynamic classes");

                foreach (string include in nestedIncludes)
                {
                    string          includeClassNameWrap = string.Empty;
                    TranslationUnit includeUnit          = Context.ASTContext.TranslationUnits.Find(unit => unit.FileNameWithoutExtension == include);

                    NodeJSTypeReferenceCollector includeReferenceCollector = new NodeJSTypeReferenceCollector(Context.ConfigurationContext, Context.TypeMaps, Context.Options);
                    includeReferenceCollector.Process(includeUnit);

                    // Find own class to wrap
                    NodeJSTypeReference includeToWrapTypeReference = includeReferenceCollector.TypeReferences
                                                                     .Where(item => item.Declaration is Class)
                                                                     .Where(item => NamingHelper.GenerateTrimmedClassName(includeUnit.FileNameWithoutExtension).ToLower().Equals(NamingHelper.GenerateTrimmedClassName(item.Declaration.Name).ToLower()))
                                                                     .FirstOrDefault();

                    // Check if nested class was found
                    if (includeToWrapTypeReference != null)
                    {
                        string className = (includeToWrapTypeReference.Declaration as Class).Name;
                        includeClassNameWrap = NamingHelper.GenerateClassWrapName(className);
                    }
                    else
                    {
                        TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
                        includeClassNameWrap = NamingHelper.GenerateClassWrapName(textInfo.ToTitleCase(includeUnit.FileNameWithoutExtension));
                    }

                    WriteLine("{0}::Initialize(target);", includeClassNameWrap);
                }

                PopBlock(NewLineKind.BeforeNextBlock);
            }

            WriteCloseBraceIndent();
            PopBlock(NewLineKind.BeforeNextBlock);
        }
示例#8
0
        private void GenerateWrapperMethods(NodeJSTypeReference classToWrapTypeReference, string classNameWrap, NodeJSTypeReferenceCollector typeReferenceCollector)
        {
            // Find class to wrap
            Class classToWrap = classToWrapTypeReference.Declaration as Class;

            // Loop over all public methods
            foreach (string methodName in methodsProcessed)
            {
                PushBlock(BlockKind.Method);
                WriteLine("NAN_METHOD({0}::{1})", classNameWrap, methodName);
                WriteStartBraceIndent();

                // Generate class object wrap
                string classNameNorm      = NamingHelper.GenerateTrimmedClassName(classToWrap.Name);
                string classNameWrapper   = NamingHelper.GenerateWrapperClassName(classToWrap.Name);
                string classNameNormLower = classNameNorm.Substring(0, 1).ToLower() + classNameNorm.Substring(1);

                PushBlock(BlockKind.MethodBody);
                WriteLine("{0}* {1} = ObjectWrap::Unwrap<{0}>(info.This());", classNameWrap, classNameWrapper);
                WriteLine("{0}* {1} = {2}->GetWrapped();", classToWrap.Name, classNameNormLower, classNameWrapper);
                PopBlock(NewLineKind.BeforeNextBlock);

                // Find overloaded methods
                IEnumerable <Method> overloadMethods = classToWrap.Methods
                                                       .Where(s => s.Name == methodName)
                                                       .OrderByDescending(s => s.Parameters.Count);

                bool firstMethodCreated = false;
                foreach (Method overloadMethod in overloadMethods)
                {
                    // Generate other constructors than default
                    string generatedIfStatement = (firstMethodCreated ? "else " : string.Empty);
                    generatedIfStatement += "if " + nodeJSTypeCheckPrinter.GenerateCheckStatement(overloadMethod.Parameters);

                    // Output arguments checker
                    PushBlock(BlockKind.MethodBody);
                    WriteLine(generatedIfStatement);
                    WriteStartBraceIndent();

                    // Generate wrapper for parameter arguments
                    string generatedArgumentsWrapped = nodeJSTypePrinter.GenerateParameterWrapper(this, overloadMethod.Parameters);
                    if (!string.IsNullOrEmpty(generatedArgumentsWrapped))
                    {
                        WriteLine("");
                    }

                    // Call wrapped method
                    WriteLine("// Call wrapped method");
                    nodeJSTypePrinter.GenerateReturnTypeWrapper(this, overloadMethod.ReturnType, string.Format("{0}->{1}({2})", classNameNormLower, overloadMethod.Name, generatedArgumentsWrapped));

                    WriteCloseBraceIndent();
                    PopBlock(NewLineKind.Never);

                    // Remember that we have created an method
                    firstMethodCreated = true;
                }

                WriteCloseBraceIndent();
                PopBlock(NewLineKind.BeforeNextBlock);
            }
        }
示例#9
0
        public void GenerateWrapperClass()
        {
            NodeJSTypeReferenceCollector typeReferenceCollector = new NodeJSTypeReferenceCollector(Context.ConfigurationContext, Context.TypeMaps, Context.Options);

            typeReferenceCollector.Process(TranslationUnit);

            List <Function> functions = typeReferenceCollector.TypeReferences
                                        .Where(item => ((item.Declaration is Function) && !(item.Declaration is Method)))
                                        .Select(item => item.Declaration as Function).ToList();

            NodeJSTypeReference classToWrapTypeReference = typeReferenceCollector.TypeReferences
                                                           .Where(item => item.Declaration is Class)
                                                           .Where(item => NamingHelper.GenerateTrimmedClassName(TranslationUnit.FileNameWithoutExtension).ToLower().Equals(NamingHelper.GenerateTrimmedClassName(item.Declaration.Name).ToLower()))
                                                           .FirstOrDefault();

            string className              = string.Empty;
            string classNameWrap          = string.Empty;
            string classNameWrapperMember = string.Empty;

            // Generate wrapper class name
            if (classToWrapTypeReference != null)
            {
                className = (classToWrapTypeReference.Declaration as Class).Name;

                // Generate wrapper and member names
                classNameWrap          = NamingHelper.GenerateClassWrapName(className);
                classNameWrapperMember = NamingHelper.GenerateClassWrapperMember(className);
            }
            else
            {
                TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
                classNameWrap = textInfo.ToTitleCase(TranslationUnit.FileNameWithoutExtension) + "Wrap";
            }

            // Generate class stub
            PushBlock(BlockKind.Class);
            WriteLine("class {0} : public node::ObjectWrap", classNameWrap);
            WriteLine("{");
            WriteLine("public:");
            PushIndent();

            // Write
            WriteLine("static NAN_MODULE_INIT(Initialize);");

            // Check if we have an class to warp
            if (!string.IsNullOrEmpty(className))
            {
                // Generate prototype templates
                WriteLine("static Nan::Persistent<v8::FunctionTemplate> prototype;");
                WriteLine("");

                // Create get wrapped method
                PushBlock(BlockKind.Method);
                WriteLine("{0}* GetWrapped() const", className);
                WriteStartBraceIndent();
                WriteLine("return {0};", classNameWrapperMember);
                PopIndent();
                WriteLine("};");
                PopBlock(NewLineKind.BeforeNextBlock);

                // Create get wrapped method
                PushBlock(BlockKind.Method);
                WriteLine("void SetWrapped({0}* {1})", className, NamingHelper.ConvertToParameterName(className));
                WriteStartBraceIndent();
                WriteLine("{0} = {1};", classNameWrapperMember, NamingHelper.ConvertToParameterName(className));
                PopIndent();
                WriteLine("};");
                PopBlock(NewLineKind.BeforeNextBlock);

                // New instance prototype
                PushBlock(BlockKind.MethodBody);
                WriteLine("static v8::Handle<v8::Value> NewInstance({0}* {1});", className, NamingHelper.ConvertToParameterName(className));
                PopBlock(NewLineKind.Always);
            }
            else
            {
                // Only add empty line when we have static functions
                if (functions.Count > 0)
                {
                    WriteLine("");
                }
            }

            // Check if we have an class to warp
            if (!string.IsNullOrEmpty(className))
            {
                // Private members prototypes
                PopIndent();
                WriteLine("private:");
                PushIndent();

                // Constructor & destructor of wrapper class
                PushBlock(BlockKind.MethodBody);
                WriteLine("static Nan::Persistent<v8::Function> constructor;");
                WriteLine("{0}(Nan::NAN_METHOD_ARGS_TYPE info);", classNameWrap);
                WriteLine("~{0}();", classNameWrap);
                WriteLine("static NAN_METHOD(New);");
                PopBlock(NewLineKind.Always);

                // Check if methods available
                if ((classToWrapTypeReference.Declaration as Class).Methods.Count > 0)
                {
                    // Methods
                    PushBlock(BlockKind.MethodBody);
                    WriteLine("// Wrapped methods");
                    SortedSet <string> methodsProcessed = new SortedSet <string>(StringComparer.InvariantCulture);
                    foreach (Method method in (classToWrapTypeReference.Declaration as Class).Methods)
                    {
                        // Skip constructors
                        if (method.IsConstructor)
                        {
                            continue;
                        }

                        // Skip on other access level than public
                        if (method.Access != AccessSpecifier.Public)
                        {
                            continue;
                        }

                        // Process method only once
                        if (methodsProcessed.Contains(method.Name))
                        {
                            continue;
                        }

                        // Output method declaration
                        WriteLine("static NAN_METHOD({0});", method.Name);
                        methodsProcessed.Add(method.Name);
                    }
                    PopBlock(NewLineKind.BeforeNextBlock);
                }
            }

            // Functions
            if (functions.Count > 0)
            {
                // Private members prototypes
                PopIndent();
                WriteLine("private:");
                PushIndent();

                PushBlock(BlockKind.MethodBody);
                WriteLine("// Wrapped functions");
                SortedSet <string> functionsProcessed = new SortedSet <string>(StringComparer.InvariantCulture);
                foreach (Function function in functions)
                {
                    // Skip on other access level than public
                    if (function.Access != AccessSpecifier.Public)
                    {
                        continue;
                    }

                    // Process method only once
                    if (functionsProcessed.Contains(function.Name))
                    {
                        continue;
                    }

                    // Output method declaration
                    WriteLine("static NAN_METHOD({0});", function.Name);
                    functionsProcessed.Add(function.Name);
                }
                PopBlock(NewLineKind.BeforeNextBlock);
            }

            // Wrapped object
            if (!string.IsNullOrEmpty(className))
            {
                // Wrapped object
                PushBlock(BlockKind.MethodBody);
                WriteLine("// Wrapped object");
                WriteLine("{0}* {1};", className, classNameWrapperMember);
                PopBlock();
            }

            PopIndent();
            WriteLine("};");

            PopBlock(NewLineKind.BeforeNextBlock);
        }