Example #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);
        }
Example #2
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);
        }
Example #3
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);
                }
            }
        }
Example #4
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);
            }
        }
Example #5
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);
        }
Example #6
0
        public string GenerateParameterWrapper(NodeJSTemplate callee, IEnumerable <Parameter> parameters)
        {
            int    parameterArgumentIndex    = 0;
            string generatedArgumentsWrapped = string.Empty;
            NodeJSTypeCheckPrinter nodeJSTypeCheckPrinter = new NodeJSTypeCheckPrinter(Context);

            foreach (Parameter parameter in parameters)
            {
                if (nodeJSTypeCheckPrinter.QualifiedTypeIsObject(parameter.QualifiedType))
                {
                    string parameterClassName    = VisitParameter(parameter, false, false);
                    string parameterClassWrapped = NamingHelper.GenerateClassWrapName(parameterClassName);

                    // Generate unwrap of stored object
                    callee.PushBlock(BlockKind.MethodBody);
                    callee.WriteLine("// Unwrap object");
                    callee.WriteLine("{0}* arg{1}_wrap = ObjectWrap::Unwrap<{0}>(info[{1}]->ToObject());", parameterClassWrapped, parameterArgumentIndex);
                    callee.WriteLine("{0}* arg{1} = arg{1}_wrap->GetWrapped();", parameterClassName, parameterArgumentIndex);
                    callee.PopBlock(NewLineKind.BeforeNextBlock);
                }
                else if (nodeJSTypeCheckPrinter.QualifiedTypeIsNumber(parameter.QualifiedType))
                {
                    // Generate wrapper for number values
                    callee.PushBlock(BlockKind.MethodBody);

                    PointerType parameterPointerType = parameter.Type as PointerType;
                    if (parameterPointerType != null && parameterPointerType.IsPointer())
                    {
                        callee.WriteLine("// Convert from number value to pointer");
                        callee.WriteLine("{0} arg{1}_value = static_cast<{0}>(info[{1}]->NumberValue());", VisitParameter(parameter, false, false), parameterArgumentIndex);
                        callee.WriteLine("{0}* arg{1} = &arg{1}_value;", VisitParameter(parameter, false, false), parameterArgumentIndex);
                    }
                    else
                    {
                        callee.WriteLine("// Convert from number value");
                        callee.WriteLine("{0} arg{1} = static_cast<{0}>(info[{1}]->NumberValue());", VisitParameter(parameter, false, false), parameterArgumentIndex);
                    }

                    callee.PopBlock(NewLineKind.BeforeNextBlock);
                }
                else if (nodeJSTypeCheckPrinter.QualifiedTypeIsBoolean(parameter.QualifiedType))
                {
                    // Generate wrapper for number values
                    callee.PushBlock(BlockKind.MethodBody);

                    PointerType parameterPointerType = parameter.Type as PointerType;
                    if (parameterPointerType != null && parameterPointerType.IsPointer())
                    {
                        callee.WriteLine("// Convert from boolean value to pointer");
                        callee.WriteLine("{0} arg{1}_value = info[{1}]->BooleanValue();", VisitParameter(parameter, false, false), parameterArgumentIndex);
                        callee.WriteLine("{0}* arg{1} = &arg{1}_value;", VisitParameter(parameter, false, false), parameterArgumentIndex);
                    }
                    else
                    {
                        callee.WriteLine("// Convert from boolean value");
                        callee.WriteLine("{0} arg{1} = info[{1}]->BooleanValue();", VisitParameter(parameter, false, false), parameterArgumentIndex);
                    }

                    callee.PopBlock(NewLineKind.BeforeNextBlock);
                }
                else if (nodeJSTypeCheckPrinter.QualifiedTypeIsString(parameter.QualifiedType))
                {
                    string parameterToWrap            = string.Format("{0}{1}", VisitParameter(parameter, false, false), (parameter.Type is PointerType ? ((parameter.Type as PointerType).IsPointer() ? "*" : string.Empty) : string.Empty));
                    string generatedStringWrapperLine = string.Format("{0} arg{1} = ", parameterToWrap, parameterArgumentIndex);
                    // Generate wrapper for string values
                    callee.PushBlock(BlockKind.MethodBody);
                    callee.WriteLine("// Convert from string value");

                    // Check if cast is needed
                    generatedStringWrapperLine += stringStaticCastFilter.Any(filter => parameterToWrap.Contains(filter)) ? string.Format("static_cast<{0}>(", parameterToWrap) : string.Empty;

                    // Generate conversation
                    generatedStringWrapperLine += string.Format("pylon_v8::ToGCString(info[{0}]->ToString())", parameterArgumentIndex);
                    generatedStringWrapperLine += parameterToWrap.Contains("wchar_t") ? ".w_str()" : ".c_str()";
                    generatedStringWrapperLine += parameterToWrap.Contains("*") ? "" : "[0]";

                    // Add closing tag if cast was needed
                    generatedStringWrapperLine += stringStaticCastFilter.Any(filter => parameterToWrap.Contains(filter)) ? ");" : ";";

                    callee.WriteLine(generatedStringWrapperLine);
                    callee.PopBlock(NewLineKind.BeforeNextBlock);
                }
                else if (nodeJSTypeCheckPrinter.QualifiedTypeIsTypedBuffer(parameter.QualifiedType))
                {
                    callee.PushBlock(BlockKind.MethodBody);
                    callee.WriteLine("// TODO: Implement wrapper for {0}", VisitParameter(parameter, false, false));
                    callee.PopBlock(NewLineKind.BeforeNextBlock);
                }

                // Store arguments for later usage
                generatedArgumentsWrapped += parameterArgumentIndex > 0 ? ", " : string.Empty;
                generatedArgumentsWrapped += parameter.Type is PointerType ? ((parameter.Type as PointerType).IsReference ? "*" : string.Empty) : string.Empty;
                generatedArgumentsWrapped += "arg" + parameterArgumentIndex;

                // Increment argument index
                parameterArgumentIndex++;
            }

            return(generatedArgumentsWrapped);
        }
Example #7
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);
        }