CsDebugScript.CodeGen.UserTypes.UserTypeFactory.AddSymbols C# (CSharp) Method

AddSymbols() private method

Adds the symbols to user type factory and generates the user types.
private AddSymbols ( IEnumerable symbols, XmlType type, string nameSpace, UserTypeGenerationFlags generationFlags ) : IEnumerable
symbols IEnumerable The template symbols grouped around the same template type.
type XmlType The XML type description.
nameSpace string The namespace.
generationFlags UserTypeGenerationFlags The user type generation flags.
return IEnumerable
        internal IEnumerable<UserType> AddSymbols(IEnumerable<Symbol> symbols, XmlType type, string nameSpace, UserTypeGenerationFlags generationFlags)
        {
            if (!type.IsTemplate && symbols.Count() > 1)
                throw new Exception("Type has more than one symbol for " + type.Name);

            if (!type.IsTemplate)
            {
                yield return AddSymbol(symbols.First(), type, nameSpace, generationFlags);
            }
            else
            {
                // Bucketize template user types based on number of template arguments
                var buckets = new Dictionary<int, List<TemplateUserType>>();

                foreach (Symbol symbol in symbols)
                {
                    UserType userType = null;

                    try
                    {
                        // We want to ignore "empty" generic classes (for now)
                        if (symbol.Name == null || symbol.Size == 0)
                            continue;

                        // Generate template user type
                        TemplateUserType templateType = new TemplateUserType(symbol, type, nameSpace, this);

            #if false // TODO: Verify if we want to use simple user type instead of template user type
                        if (templateType.AllTemplateArguments.Count == 0)
                        {
                            // Template does not have arguments that can be used by generic
                            // Make it specialized type
                            userType = this.AddSymbol(symbol, null, moduleName, generationOptions);
                        }
                        else
            #endif
                        {
                            List<TemplateUserType> templates;

                            symbol.UserType = templateType;
                            if (!buckets.TryGetValue(templateType.AllTemplateArguments.Count, out templates))
                                buckets.Add(templateType.AllTemplateArguments.Count, templates = new List<TemplateUserType>());
                            templates.Add(templateType);
                        }
                    }
                    catch (Exception ex)
                    {
                        // TODO: Verify if we need to add this as specialization
                        if (ex.Message != "Wrongly formed template argument")
                            throw;
                    }

                    if (userType != null)
                        yield return userType;
                }

                // Add newly generated types
                foreach (List<TemplateUserType> templatesInBucket in buckets.Values)
                {
                    // TODO: Verify that all templates in the list can be described by the same class (also do check for inner-types)

                    // Sort Templates by Class Name.
                    // This removes ambiguity caused by parallel type processing.
                    //
                    List<TemplateUserType> templates = templatesInBucket.OrderBy(t => t.Symbol.Name.Count(c => c == '*'))
                        .ThenBy(t => t.Symbol.Name.Count(c => c == '<'))
                        .ThenBy(t => t.Symbol.Name).ToList();

                    // Select best suited type for template
                    TemplateUserType template = templates.First();

                    foreach (var specializedTemplate in templates)
                    {
                        var arguments = specializedTemplate.AllTemplateArguments;

                        // Check if all arguments are different
                        if (arguments.Distinct().Count() == arguments.Count())
                        {
                            // Check if all arguments are simple user type
                            bool simpleUserType = true;

                            foreach (var argument in arguments)
                            {
                                var argumentSymbol = GlobalCache.GetSymbol(argument, specializedTemplate.Module);

                                if (argumentSymbol.Tag != SymTagEnum.SymTagUDT || argumentSymbol.Name.Contains("<"))
                                {
                                    simpleUserType = false;
                                    break;
                                }
                            }

                            if (simpleUserType)
                            {
                                template = specializedTemplate;
                                break;
                            }

                            // Check if none of the arguments is template user type
                            bool noneIsTemplate = true;

                            foreach (var argument in arguments)
                            {
                                var argumentSymbol = GlobalCache.GetSymbol(argument, specializedTemplate.Module);

                                if (argumentSymbol.Tag == SymTagEnum.SymTagUDT && argumentSymbol.Name.Contains("<"))
                                {
                                    noneIsTemplate = false;
                                    break;
                                }
                            }

                            if (noneIsTemplate)
                            {
                                template = specializedTemplate;
                                continue;
                            }
                        }

                        // This one is as good as any...
                    }

                    // Move all types under the selected type
                    foreach (var specializedTemplate in templates)
                    {
                        template.SpecializedTypes.Add(specializedTemplate);
                        specializedTemplate.TemplateType = template;
                    }

                    yield return template;
                }
            }
        }