Exemplo n.º 1
0
        private void GenerateWrapperFunctions(string classNameWrap, NodeJSTypeReferenceCollector typeReferenceCollector)
        {
            // Loop over all static functions
            foreach (string functionName in functionsProcessed)
            {
                PushBlock(BlockKind.Method);
                WriteLine("NAN_METHOD({0}::{1})", classNameWrap, functionName);
                WriteStartBraceIndent();

                // Find overloaded static functions
                IEnumerable <Function> functionOverloads = typeReferenceCollector.TypeReferences
                                                           .Where(item => ((item.Declaration is Function) && !(item.Declaration is Method)))
                                                           .Select(item => item.Declaration as Function)
                                                           .Where(s => s.Name == functionName).OrderByDescending(s => s.Parameters.Count);

                bool firstFunctionCreated = false;
                foreach (Function overloadFunction in functionOverloads)
                {
                    // Generate other constructors than default
                    string generatedIfStatement = (firstFunctionCreated ? "else " : string.Empty);
                    generatedIfStatement += "if " + nodeJSTypeCheckPrinter.GenerateCheckStatement(overloadFunction.Parameters);

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

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

                    // Call wrapped method
                    WriteLine("// Call wrapped function");
                    nodeJSTypePrinter.GenerateReturnTypeWrapper(this, overloadFunction.ReturnType, string.Format("{0}({1})", overloadFunction.Name, generatedArgumentsWrapped));

                    WriteCloseBraceIndent();
                    PopBlock(NewLineKind.Never);

                    // Remember that we have created an function
                    firstFunctionCreated = true;
                }

                WriteCloseBraceIndent();
                PopBlock(NewLineKind.BeforeNextBlock);
            }
        }
Exemplo n.º 2
0
        public void GenerateIncludeForwardRefernces()
        {
            NodeJSTypeReferenceCollector typeReferenceCollector = new NodeJSTypeReferenceCollector(Context.ConfigurationContext, Context.TypeMaps, Context.Options);

            typeReferenceCollector.Process(TranslationUnit, filterNamespaces: false);

            // Filter for needed includes
            SortedSet <string> includes = new SortedSet <string>(StringComparer.InvariantCulture);

            foreach (NodeJSTypeReference typeRef in typeReferenceCollector.TypeReferences)
            {
                if (typeRef.Include.TranslationUnit == TranslationUnit)
                {
                    continue;
                }

                if (typeRef.Include.File == TranslationUnit.FileName)
                {
                    continue;
                }

                Include         include = typeRef.Include;
                TranslationUnit unit    = include.TranslationUnit;

                if (unit != null && !unit.IsDeclared)
                {
                    continue;
                }

                if (!string.IsNullOrEmpty(include.File) && include.InHeader)
                {
                    includes.Add(include.ToString());
                }
            }

            // Output include lines
            foreach (string include in includes)
            {
                WriteLine(include);
            }
        }
Exemplo n.º 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);
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Generate using directives
        /// </summary>
        public void GenerateNamespaceUsings()
        {
            NodeJSTypeReferenceCollector typeReferenceCollector = new NodeJSTypeReferenceCollector(Context.ConfigurationContext, Context.TypeMaps, Context.Options);

            typeReferenceCollector.Process(TranslationUnit);

            // Create sorted list of namespaces
            SortedSet <string> namespaces = new SortedSet <string>(StringComparer.InvariantCulture);

            foreach (NodeJSTypeReference typeRef in typeReferenceCollector.TypeReferences)
            {
                // Check if declaration namespace is set
                if (typeRef.Declaration.Namespace != null)
                {
                    namespaces.Add(typeRef.Declaration.Namespace.ToString());
                }
            }

            // Output @namespace lines
            foreach (string @namespace in namespaces)
            {
                WriteLine("using namespace {0};", @namespace);
            }
        }
Exemplo n.º 5
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);
            }
        }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
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);
            }
        }
Exemplo n.º 8
0
        public override bool VisitASTContext(ASTContext context)
        {
            SortedList <string, TranslationUnit> missingTranslationUnits = new SortedList <string, TranslationUnit>();

            // Get list of generated units
            List <TranslationUnit> units = Context.ASTContext.TranslationUnits.GetGenerated().ToList();

            foreach (TranslationUnit unit in units)
            {
                NodeJSTypeReferenceCollector typeReferenceCollector = new NodeJSTypeReferenceCollector(Context.ConfigurationContext, Context.TypeMaps, Context.Options);
                typeReferenceCollector.Process(unit);

                IEnumerable <NodeJSTypeReference> classToWrapTypeReferences = typeReferenceCollector.TypeReferences
                                                                              .Where(item => item.Declaration is Class);

                // Check if no class reference where found
                if (classToWrapTypeReferences.Count() > 0)
                {
                    foreach (NodeJSTypeReference currentReference in classToWrapTypeReferences)
                    {
                        // Check if missing unit was already added
                        if (missingTranslationUnits.ContainsKey(currentReference.Declaration.Name))
                        {
                            continue;
                        }

                        // Check if missing unit exists with trimmed name
                        if (units.Exists(u => NamingHelper.GenerateTrimmedClassName(u.FileNameWithoutExtension).ToLower().Contains(NamingHelper.GenerateTrimmedClassName(currentReference.Declaration.Name).ToLower())))
                        {
                            continue;
                        }

                        // Make deep copy of current unit
                        TranslationUnit missingTranslationUnit = unit.Copy();

                        // Change names of copy
                        missingTranslationUnit.Name         = currentReference.Declaration.Name;
                        missingTranslationUnit.OriginalName = currentReference.Declaration.Name;

                        // Change public fields
                        string missingTranslationUnitFileName         = NamingHelper.GenerateTrimmedClassName(currentReference.Declaration.Name).ToLower() + ".gen";
                        string missingTranslationUnitFileRelativePath = unit.FileRelativePath;

                        // Update public fields
                        missingTranslationUnit.FilePath = Path.Combine(Path.GetDirectoryName(unit.FilePath), missingTranslationUnitFileName);

                        // Update private fields with reflection
                        FieldInfo fileNameFieldInfo = missingTranslationUnit.GetType().GetField("fileName", BindingFlags.NonPublic | BindingFlags.Instance);
                        fileNameFieldInfo.SetValue(missingTranslationUnit, missingTranslationUnitFileName);

                        FieldInfo fileNameWithoutExtensionFieldInfo = missingTranslationUnit.GetType().GetField("fileNameWithoutExtension", BindingFlags.NonPublic | BindingFlags.Instance);
                        fileNameWithoutExtensionFieldInfo.SetValue(missingTranslationUnit, Path.GetFileNameWithoutExtension(missingTranslationUnitFileName));

                        FieldInfo fileRelativeDirectoryFieldInfo = missingTranslationUnit.GetType().GetField("fileRelativeDirectory", BindingFlags.NonPublic | BindingFlags.Instance);
                        fileRelativeDirectoryFieldInfo.SetValue(missingTranslationUnit, Path.GetDirectoryName(missingTranslationUnitFileRelativePath));

                        FieldInfo fileRelativePathFieldInfo = missingTranslationUnit.GetType().GetField("fileRelativePath", BindingFlags.NonPublic | BindingFlags.Instance);
                        fileRelativePathFieldInfo.SetValue(missingTranslationUnit, Path.Combine(Path.GetDirectoryName(missingTranslationUnitFileRelativePath), missingTranslationUnitFileName));

                        // Add to collection for later processing
                        missingTranslationUnits.Add(currentReference.Declaration.Name, missingTranslationUnit);
                    }
                }
            }

            // Insert missing items
            Context.ASTContext.TranslationUnits.AddRange(missingTranslationUnits.Values);

            return(true);
        }
Exemplo n.º 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);
        }