コード例 #1
0
        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;
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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;
        }
コード例 #5
0
        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;
            }
        }
コード例 #6
0
        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;
        }
コード例 #7
0
        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);
            }
        }
コード例 #8
0
        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);
                }
            }
        }