void ParseTemplateBaseCursor(Cursor cursor) { var tokens = _context.TranslationUnit.Tokenize(cursor.Extent) .TakeWhile(t => !t.Spelling.Equals("{")) .SkipWhile(t => !t.Spelling.Equals(":")); if (!tokens.Any()) { return; } var baseTokens = tokens.ToList(); int templSpecStart = -1, templSpecEnd = -1; for (int i = 0; i < baseTokens.Count; i++) { var token = baseTokens[i]; if (token.Spelling == "<") { templSpecStart = i; } else if (token.Spelling == ">") { templSpecEnd = i; } } if (templSpecStart != -1 && templSpecEnd != -1) { string template = baseTokens[templSpecStart - 1].Spelling; string templateSpec = string.Join(" ", baseTokens.GetRange(templSpecStart + 1, templSpecEnd - templSpecStart - 1) .Select(t => t.Spelling)); templateSpec = TypeRefDefinition.GetBasicName(templateSpec); string templateName = $"{template}<{templateSpec}>"; ClassDefinition classTemplate; if (!project.ClassDefinitions.TryGetValue(templateName, out classTemplate)) { var classTemplateNew = new ClassTemplateDefinition(template, _context.Header); classTemplateNew.TemplateParameters.Add(templateSpec); var baseTemplate = project.ClassDefinitions.FirstOrDefault(c => c.Value.Name.Equals(template)); classTemplateNew.BaseClass = baseTemplate.Value; project.ClassDefinitions[templateName] = classTemplateNew; _context.Header.Classes.Add(classTemplateNew); classTemplate = classTemplateNew; } _context.Class.BaseClass = classTemplate; } }
private void CopyTemplateMethods(ClassDefinition thisClass, ClassTemplateDefinition template, Dictionary <string, string> templateParams = null) { if (templateParams == null) { templateParams = new Dictionary <string, string>(); var templateBase = template.BaseClass as ClassTemplateDefinition; for (int i = 0; i < template.TemplateParameters.Count; i++) { string param = templateBase.TemplateParameters[i]; string paramValue = template.TemplateParameters[i]; templateParams[param] = TypeRefDefinition.GetBasicName(paramValue); } CopyTemplateMethods(thisClass, templateBase, templateParams); return; } thisClass.BaseClass = template.BaseClass; var scriptedNameMapping = Project.ClassNameMapping as ScriptedMapping; if (scriptedNameMapping != null) { scriptedNameMapping.Globals.Header = thisClass.Header; } // TODO: //template.ManagedName = Project.ClassNameMapping.Map(template.Name); foreach (var templateClass in template.NestedClasses) { var classSpec = new ClassDefinition(templateClass.Name, thisClass.Header, thisClass); Project.ClassDefinitions.Add(classSpec.FullyQualifiedName, classSpec); foreach (var templateMethod in templateClass.Methods) { SpecializeTemplateMethod(classSpec, templateMethod, templateParams); } } foreach (var templateMethod in template.Methods.Where(m => !m.IsConstructor)) { SpecializeTemplateMethod(thisClass, templateMethod, templateParams); } }
protected static string GetFullNameC(ClassDefinition @class) { string className; ClassTemplateDefinition template = @class as ClassTemplateDefinition; if (template != null) { className = @class.Name + string.Join("_", template.TemplateParameters); } else { className = @class.Name; } if (@class.Parent != null) { return($"{GetFullNameC(@class.Parent)}_{@class.Name}"); } if (@class.NamespaceName != "") { return($"{@class.NamespaceName}_{@class.Name}"); } return(@class.Name); }
void ParseClassCursor(Cursor cursor) { string className = cursor.Spelling; string fullyQualifiedName = TypeRefDefinition.GetFullyQualifiedName(cursor); ClassDefinition @class; if (project.ClassDefinitions.TryGetValue(fullyQualifiedName, out @class)) { if (@class.IsParsed) return; @class.Parent = _context.Class; } else { switch(cursor.Kind) { case CursorKind.ClassTemplate: @class = new ClassTemplateDefinition(className, _context.Header, _context.Class); break; case CursorKind.EnumDecl: @class = new EnumDefinition(className, _context.Header, _context.Class); break; default: @class = new ClassDefinition(className, _context.Header, _context.Class); break; } @class.NamespaceName = _context.Namespace; if (@class.FullyQualifiedName != fullyQualifiedName) { Console.WriteLine("Parsing error at " + fullyQualifiedName); } project.ClassDefinitions[fullyQualifiedName] = @class; } _context.Class = @class; _context.Class.IsParsed = true; // Unnamed struct escapes to the surrounding scope if (!(string.IsNullOrEmpty(className) && cursor.Kind == CursorKind.StructDecl)) { if (_context.Class.Parent != null) { _context.Class.Parent.NestedClasses.Add(_context.Class); } else { _context.Header.Classes.Add(_context.Class); } } AccessSpecifier parentMemberAccess = _context.MemberAccess; // Default class/struct access specifier switch (cursor.Kind) { case CursorKind.ClassDecl: _context.MemberAccess = AccessSpecifier.Private; break; case CursorKind.StructDecl: _context.Class.IsStruct = true; _context.MemberAccess = AccessSpecifier.Public; break; case CursorKind.ClassTemplate: if (cursor.TemplateCursorKind != CursorKind.ClassDecl) { _context.MemberAccess = AccessSpecifier.Private; } else { _context.MemberAccess = AccessSpecifier.Public; } break; case CursorKind.TypedefDecl: var underlying = cursor.TypedefDeclUnderlyingType.Canonical; if (underlying.TypeKind == ClangSharp.Type.Kind.Pointer && underlying.Pointee.TypeKind == ClangSharp.Type.Kind.FunctionProto) { _context.Class.IsFunctionProto = true; } break; } if (cursor.Kind == CursorKind.EnumDecl) { var @enum = _context.Class as EnumDefinition; foreach (var constantDecl in cursor.Children .Where(c => c.Kind == CursorKind.EnumConstantDecl)) { string valueSpelling = ""; var value = constantDecl.Children.FirstOrDefault(); if (value != null) { var valueTokens = _context.TranslationUnit.Tokenize(value.Extent) .Where(t => t.Kind != TokenKind.Comment && !t.Spelling.Equals(",") && !t.Spelling.Equals("}")); valueSpelling = string.Join("", valueTokens.Select(t => t.Spelling)); } @enum.EnumConstants.Add(new EnumConstant(constantDecl.Spelling, valueSpelling)); } } else { cursor.VisitChildren(ClassVisitor); if (_context.Class.BaseClass == null) { // Clang doesn't give the base class if it's a template, // tokenize the class definition and extract the base template if it exists ParseTemplateBaseCursor(cursor); } } // Restore parent state _context.Class = _context.Class.Parent; _context.MemberAccess = parentMemberAccess; }
void ParseTemplateBaseCursor(Cursor cursor) { var tokens = _context.TranslationUnit.Tokenize(cursor.Extent) .TakeWhile(t => !t.Spelling.Equals("{")) .SkipWhile(t => !t.Spelling.Equals(":")); if (!tokens.Any()) return; var baseTokens = tokens.ToList(); int templSpecStart = -1, templSpecEnd = -1; for (int i = 0; i < baseTokens.Count; i++) { var token = baseTokens[i]; if (token.Spelling == "<") { templSpecStart = i; } else if (token.Spelling == ">") { templSpecEnd = i; } } if (templSpecStart != -1 && templSpecEnd != -1) { string template = baseTokens[templSpecStart - 1].Spelling; string templateSpec = string.Join(" ", baseTokens.GetRange(templSpecStart + 1, templSpecEnd - templSpecStart - 1) .Select(t => t.Spelling)); templateSpec = TypeRefDefinition.GetBasicName(templateSpec); string templateName = $"{template}<{templateSpec}>"; ClassDefinition classTemplate; if (!project.ClassDefinitions.TryGetValue(templateName, out classTemplate)) { var classTemplateNew = new ClassTemplateDefinition(template, _context.Header); classTemplateNew.TemplateParameters.Add(templateSpec); var baseTemplate = project.ClassDefinitions.FirstOrDefault(c => c.Value.Name.Equals(template)); classTemplateNew.BaseClass = baseTemplate.Value; project.ClassDefinitions[templateName] = classTemplateNew; _context.Header.Classes.Add(classTemplateNew); classTemplate = classTemplateNew; } _context.Class.BaseClass = classTemplate; } }
void ParseClassCursor(Cursor cursor) { string className = cursor.Spelling; string fullyQualifiedName = TypeRefDefinition.GetFullyQualifiedName(cursor); ClassDefinition @class; if (project.ClassDefinitions.TryGetValue(fullyQualifiedName, out @class)) { if (@class.IsParsed) { return; } @class.Parent = _context.Class; } else { switch (cursor.Kind) { case CursorKind.ClassTemplate: @class = new ClassTemplateDefinition(className, _context.Header, _context.Class); break; case CursorKind.EnumDecl: @class = new EnumDefinition(className, _context.Header, _context.Class); break; default: @class = new ClassDefinition(className, _context.Header, _context.Class); break; } @class.NamespaceName = _context.Namespace; if (@class.FullyQualifiedName != fullyQualifiedName) { Console.WriteLine("Parsing error at " + fullyQualifiedName); } project.ClassDefinitions[fullyQualifiedName] = @class; } _context.Class = @class; _context.Class.IsParsed = true; // Unnamed struct escapes to the surrounding scope if (!(string.IsNullOrEmpty(className) && cursor.Kind == CursorKind.StructDecl)) { if (_context.Class.Parent != null) { _context.Class.Parent.NestedClasses.Add(_context.Class); } else { _context.Header.Classes.Add(_context.Class); } } AccessSpecifier parentMemberAccess = _context.MemberAccess; // Default class/struct access specifier switch (cursor.Kind) { case CursorKind.ClassDecl: _context.MemberAccess = AccessSpecifier.Private; break; case CursorKind.StructDecl: _context.Class.IsStruct = true; _context.MemberAccess = AccessSpecifier.Public; break; case CursorKind.ClassTemplate: if (cursor.TemplateCursorKind != CursorKind.ClassDecl) { _context.MemberAccess = AccessSpecifier.Private; } else { _context.MemberAccess = AccessSpecifier.Public; } break; case CursorKind.TypedefDecl: var underlying = cursor.TypedefDeclUnderlyingType.Canonical; if (underlying.TypeKind == ClangSharp.Type.Kind.Pointer && underlying.Pointee.TypeKind == ClangSharp.Type.Kind.FunctionProto) { _context.Class.IsFunctionProto = true; } break; } if (cursor.Kind == CursorKind.EnumDecl) { var @enum = _context.Class as EnumDefinition; foreach (var constantDecl in cursor.Children .Where(c => c.Kind == CursorKind.EnumConstantDecl)) { string valueSpelling = ""; var value = constantDecl.Children.FirstOrDefault(); if (value != null) { var valueTokens = _context.TranslationUnit.Tokenize(value.Extent) .Where(t => t.Kind != TokenKind.Comment && !t.Spelling.Equals(",") && !t.Spelling.Equals("}")); valueSpelling = string.Join("", valueTokens.Select(t => t.Spelling)); } @enum.EnumConstants.Add(new EnumConstant(constantDecl.Spelling, valueSpelling)); } } else { cursor.VisitChildren(ClassVisitor); if (_context.Class.BaseClass == null) { // Clang doesn't give the base class if it's a template, // tokenize the class definition and extract the base template if it exists ParseTemplateBaseCursor(cursor); } } // Restore parent state _context.Class = _context.Class.Parent; _context.MemberAccess = parentMemberAccess; }
private void CopyTemplateMethods(ClassDefinition thisClass, ClassTemplateDefinition template, Dictionary<string, string> templateParams = null) { if (templateParams == null) { templateParams = new Dictionary<string, string>(); var templateBase = template.BaseClass as ClassTemplateDefinition; for (int i = 0; i < template.TemplateParameters.Count; i++) { string param = templateBase.TemplateParameters[i]; string paramValue = template.TemplateParameters[i]; templateParams[param] = TypeRefDefinition.GetBasicName(paramValue); } CopyTemplateMethods(thisClass, templateBase, templateParams); return; } thisClass.BaseClass = template.BaseClass; var scriptedNameMapping = Project.ClassNameMapping as ScriptedMapping; if (scriptedNameMapping != null) { scriptedNameMapping.Globals.Header = thisClass.Header; } // TODO: //template.ManagedName = Project.ClassNameMapping.Map(template.Name); foreach (var templateClass in template.NestedClasses) { var classSpec = new ClassDefinition(templateClass.Name, thisClass.Header, thisClass); Project.ClassDefinitions.Add(classSpec.FullyQualifiedName, classSpec); foreach (var templateMethod in templateClass.Methods) { SpecializeTemplateMethod(classSpec, templateMethod, templateParams); } } foreach (var templateMethod in template.Methods.Where(m => !m.IsConstructor)) { SpecializeTemplateMethod(thisClass, templateMethod, templateParams); } }
private void CopyTemplateMethods(ClassDefinition thisClass, ClassTemplateDefinition template, Dictionary <string, string> templateParams = null) { if (templateParams == null) { templateParams = new Dictionary <string, string>(); var templateBase = template.BaseClass as ClassTemplateDefinition; for (int i = 0; i < template.TemplateParameters.Count; i++) { string param = templateBase.TemplateParameters[i]; string paramValue = template.TemplateParameters[i]; templateParams[param] = paramValue; } CopyTemplateMethods(thisClass, templateBase, templateParams); return; } thisClass.BaseClass = template.BaseClass; var scriptedNameMapping = Project.ClassNameMapping as ScriptedMapping; if (scriptedNameMapping != null) { scriptedNameMapping.Globals.Header = thisClass.Header; } // TODO: //template.ManagedName = Project.ClassNameMapping.Map(template.Name); foreach (var templateClass in template.NestedClasses) { var classSpec = new ClassDefinition(templateClass.Name, thisClass.Header, thisClass); Project.ClassDefinitions.Add(classSpec.FullyQualifiedName, classSpec); foreach (var templateMethod in templateClass.Methods) { // Replace template parameters with concrete types var methodSpec = templateMethod.Copy(classSpec); if (methodSpec.ReturnType.HasTemplateTypeParameter) { methodSpec.ReturnType = methodSpec.ReturnType.CopyTemplated(templateParams); } foreach (var param in methodSpec.Parameters .Where(p => p.Type.HasTemplateTypeParameter)) { param.Type = param.Type.CopyTemplated(templateParams); } } } foreach (var templateMethod in template.Methods.Where(m => !m.IsConstructor)) { // Replace template parameters with concrete types var methodSpec = templateMethod.Copy(thisClass); if (methodSpec.ReturnType.HasTemplateTypeParameter) { methodSpec.ReturnType = methodSpec.ReturnType.CopyTemplated(templateParams); } foreach (var param in methodSpec.Parameters .Where(p => p.Type.HasTemplateTypeParameter)) { param.Type = param.Type.CopyTemplated(templateParams); } } }