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); } } }
private IEnumerable <string> GetNestedIncludes(string classNameWrap) { IEnumerable <ConfigMapping> configFilesLoaded = Context.ConfigurationContext.ConfigFilesLoaded; foreach (ConfigMapping configFileLoad in configFilesLoaded) { string configFileLoadedName = (configFileLoad.Module != null ? NamingHelper.GenerateTrimmedClassName(configFileLoad.Module) : string.Empty); if (!(string.IsNullOrEmpty(configFileLoadedName))) { TextInfo textInfo = new CultureInfo("en-US", false).TextInfo; string configFileLoadedWrappedName = textInfo.ToTitleCase(configFileLoadedName) + "Wrap"; if (configFileLoadedWrappedName == classNameWrap) { // Workaround for GeniCam files if (configFileLoadedName.ToLower().Contains("genicam")) { // Search all GeniCam related files and remove doubles return(Context.ASTContext.TranslationUnits.GetGenerated() .Where(unit => !unit.FileRelativeDirectory.ToLower().Contains("pylon")) .Where(unit => !string.IsNullOrEmpty(unit.FileRelativeDirectory)) .Select(unit => unit.FileNameWithoutExtension).Distinct().ToList()); } else { // Search all pylon related files and remove doubles return(Context.ASTContext.TranslationUnits.GetGenerated() .Where(unit => unit.FileRelativeDirectory.ToLower().Contains(configFileLoadedName.ToLower())) .Select(unit => unit.FileNameWithoutExtension).Distinct().ToList()); } } } } // Return empty list return(new List <string>()); }
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); } }
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); }
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); } }
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); }
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); }
public override TypePrinterResult VisitUnsupportedType(UnsupportedType type, TypeQualifiers quals) { // Mapping Enums to Number type if (type.Description.StartsWith("E")) { return(NodeV8IsNumber); } if (type.Description.EndsWith("Enums")) { return(NodeV8IsNumber); } // Search for known objects if (Context.ASTContext.TranslationUnits.GetGenerated().ToList().Exists(u => NamingHelper.GenerateTrimmedClassName(u.FileNameWithoutExtension).ToLower().Equals(NamingHelper.GenerateTrimmedClassName(type.Description).ToLower()))) { return(NodeV8IsObject); } // Mapping special Windows types if (type.Description.StartsWith("wchar_t")) { return(NodeV8IsString); } // Map other unknown always as buffer type return(NodeV8IsTypedBuffer); }