예제 #1
0
        /// <summary>
        /// Extracts all fields from the user type.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        protected override IEnumerable<UserTypeField> ExtractFields(UserTypeFactory factory, UserTypeGenerationFlags generationFlags)
        {
            ExportStaticFields = true;

            var fields = Symbol.Fields.OrderBy(s => s.Name).ToArray();
            bool useThisClass = generationFlags.HasFlag(UserTypeGenerationFlags.UseClassFieldsFromDiaSymbolProvider);
            string previousName = "";

            foreach (var field in fields)
            {
                if (string.IsNullOrEmpty(field.Type.Name))
                    continue;

                if (IsFieldFiltered(field) || field.Name == previousName)
                    continue;

                if (field.Name.Contains("@"))
                {
                    // Skip names contaings '@'
                    continue;
                }

                // Skip fields that are actual values of enum values
                if (field.Type.Tag == Dia2Lib.SymTagEnum.SymTagEnum && field.Type.GetEnumValues().Any(t => t.Item1 == field.Name))
                    continue;

                var userField = ExtractField(field, factory, generationFlags, forceIsStatic: true);

                if (field.Type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType)
                {
                    // Do not use const values for pointers.
                    // We do not allow user type implicit conversion from integers.
                    userField.ConstantValue = string.Empty;
                }

                userField.FieldName = NormalizeSymbolNamespace(userField.FieldName);
                userField.PropertyName = NormalizeSymbolNamespace(userField.PropertyName);

                yield return userField;
                previousName = field.Name;
            }

            foreach (var field in GetAutoGeneratedFields(false, useThisClass))
                    yield return field;
        }
예제 #2
0
        /// <summary>
        /// Adds the symbol to user type factory and generates the user type.
        /// </summary>
        /// <param name="symbol">The non-template symbol.</param>
        /// <param name="type">The XML type description.</param>
        /// <param name="nameSpace">The namespace.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <returns>Generated user type for the specified symbol.</returns>
        internal UserType AddSymbol(Symbol symbol, XmlType type, string nameSpace, UserTypeGenerationFlags generationFlags)
        {
            UserType userType;

            if (symbol.Tag == SymTagEnum.SymTagEnum)
            {
                userType = new EnumUserType(symbol, nameSpace);
            }
            else if (symbol.Tag == SymTagEnum.SymTagExe)
            {
                userType = new GlobalsUserType(symbol, type, nameSpace);
            }
            else if (generationFlags.HasFlag(UserTypeGenerationFlags.GeneratePhysicalMappingOfUserTypes))
            {
                userType = new PhysicalUserType(symbol, type, nameSpace);
            }
            else
            {
                userType = new UserType(symbol, type, nameSpace);
            }

            symbol.UserType = userType;
            return userType;
        }
예제 #3
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            // Check if we need to write namespace
            string nameSpace = (DeclaredInType as NamespaceUserType)?.FullClassName ?? Namespace;

            if ((DeclaredInType == null || (!generationFlags.HasFlag(UserTypeGenerationFlags.SingleFileExport) && DeclaredInType is NamespaceUserType)) && !string.IsNullOrEmpty(nameSpace))
            {
                output.WriteLine(indentation, "namespace {0}", nameSpace);
                output.WriteLine(indentation++, "{{");
            }

            // Write beginning of the enumeration
            if (generationFlags.HasFlag(UserTypeGenerationFlags.GenerateFieldTypeInfoComment))
                output.WriteLine(indentation, "// {0} (original name: {1})", ClassName, Symbol.Name);

            if (AreValuesFlags())
                output.WriteLine(indentation, @"[System.Flags]");
            if (Symbol.Size != 0)
                output.WriteLine(indentation, @"public enum {0} : {1}", ClassName, GetEnumBasicType(Symbol));
            else
                output.WriteLine(indentation, @"public enum {0}", ClassName);
            output.WriteLine(indentation++, @"{{");

            // Write values
            foreach (var enumValue in Symbol.GetEnumValues())
            {
                output.WriteLine(indentation, "{0} = {1},", enumValue.Item1, enumValue.Item2);
            }

            // Enumeration end
            output.WriteLine(--indentation, @"}}");
            if ((DeclaredInType == null || (!generationFlags.HasFlag(UserTypeGenerationFlags.SingleFileExport) && DeclaredInType is NamespaceUserType)) && !string.IsNullOrEmpty(nameSpace))
            {
                output.WriteLine(--indentation, "}}");
            }
        }
예제 #4
0
        /// <summary>
        /// Adds the symbols to user type factory and generates the user types.
        /// </summary>
        /// <param name="symbols">The template symbols grouped around the same template type.</param>
        /// <param name="type">The XML type description.</param>
        /// <param name="nameSpace">The namespace.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <returns>Generated user types for the specified symbols.</returns>
        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;
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Adds template symbols to user type factory and generates template user types.
        /// </summary>
        /// <param name="symbols">The template symbols grouped around the same template type.</param>
        /// <param name="nameSpace">The namespace.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <returns>Generated user types for the specified symbols.</returns>
        internal IEnumerable <UserType> AddTemplateSymbols(IEnumerable <Symbol> symbols, string nameSpace, UserTypeGenerationFlags generationFlags)
        {
            // Bucketize template user types based on number of template arguments
            var buckets = new Dictionary <int, List <SpecializedTemplateUserType> >();

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

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

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

                if (!templateType.WronglyFormed)
                {
                    List <SpecializedTemplateUserType> templates;

                    symbol.UserType = templateType;
                    if (!buckets.TryGetValue(templateType.AllTemplateArguments.Count, out templates))
                    {
                        buckets.Add(templateType.AllTemplateArguments.Count, templates = new List <SpecializedTemplateUserType>());
                    }
                    templates.Add(templateType);
                }

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

            // Add newly generated types
            foreach (List <SpecializedTemplateUserType> 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 <SpecializedTemplateUserType> 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
                SpecializedTemplateUserType template = templates.First();
                int bestScore = int.MaxValue;

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

                    for (int i = 0; i < arguments.Count; i++)
                    {
                        var argument = arguments[i];

                        // Check if this is repeated type
                        bool repeated = false;

                        for (int j = 0; j < i && !repeated; j++)
                        {
                            repeated = argument == arguments[j];
                        }
                        if (repeated)
                        {
                            score += 100;
                        }

                        // Check if argument is constant
                        if (argument.Tag == CodeTypeTag.TemplateArgumentConstant)
                        {
                            continue;
                        }

                        // Check if argument is simple user type
                        if ((argument.Tag == CodeTypeTag.Class || argument.Tag == CodeTypeTag.Structure || argument.Tag == CodeTypeTag.Union || argument.Tag == CodeTypeTag.Enum) && !argument.Name.Contains("<"))
                        {
                            score += 1;
                            continue;
                        }

                        // Check if argments is function
                        if (argument.Tag == CodeTypeTag.Function)
                        {
                            score += 2;
                            continue;
                        }

                        // Check if argument is template
                        if (argument.Name.Contains("<"))
                        {
                            score += 20;
                            continue;
                        }

                        // All others fall into the same category
                        score += 5;
                    }

                    // Check if this is the best one
                    if (score < bestScore)
                    {
                        bestScore = score;
                        template  = specializedTemplate;
                    }
                }

                yield return(new TemplateUserType(template, templates, this));
            }
        }
예제 #6
0
        /// <summary>
        /// Generates user types using the specified XML configuration.
        /// </summary>
        /// <param name="xmlConfig">The XML configuration.</param>
        /// <param name="logger">The logger text writer. If set to null, Console.Out will be used.</param>
        /// <param name="errorLogger">The error logger text writer. If set to null, Console.Error will be used.</param>
        public static void Generate(XmlConfig xmlConfig, TextWriter logger = null, TextWriter errorLogger = null)
        {
            var sw = System.Diagnostics.Stopwatch.StartNew();

            XmlModule[]             xmlModules                   = xmlConfig.Modules;
            XmlType[]               typeNames                    = xmlConfig.Types;
            XmlIncludedFile[]       includedFiles                = xmlConfig.IncludedFiles;
            XmlReferencedAssembly[] referencedAssemblies         = xmlConfig.ReferencedAssemblies;
            UserTypeGenerationFlags generationOptions            = xmlConfig.GetGenerationFlags();
            ConcurrentDictionary <string, string> generatedFiles = new ConcurrentDictionary <string, string>();
            var    syntaxTrees      = new ConcurrentBag <SyntaxTree>();
            string currentDirectory = Directory.GetCurrentDirectory();
            string outputDirectory  = currentDirectory + "\\output\\";

            // Check logger and error logger
            if (errorLogger == null)
            {
                errorLogger = Console.Error;
            }
            if (logger == null)
            {
                logger = Console.Out;
            }

            // Create output directory
            Directory.CreateDirectory(outputDirectory);

            // Verify that included files exist
            if (!string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName))
            {
                foreach (var file in includedFiles)
                {
                    if (!File.Exists(file.Path))
                    {
                        throw new FileNotFoundException("", file.Path);
                    }
                }
            }

            // Loading modules
            ConcurrentDictionary <Module, XmlModule>   modules = new ConcurrentDictionary <Module, XmlModule>();
            ConcurrentDictionary <XmlModule, Symbol[]> globalTypesPerModule = new ConcurrentDictionary <XmlModule, Symbol[]>();

            logger.Write("Loading modules...");
            Parallel.ForEach(xmlModules, (xmlModule) =>
            {
                Module module = Module.Open(xmlModule);

                modules.TryAdd(module, xmlModule);
            });

            logger.WriteLine(" {0}", sw.Elapsed);

            // Enumerating symbols
            logger.Write("Enumerating symbols...");
            Parallel.ForEach(modules, (mm) =>
            {
                XmlModule xmlModule   = mm.Value;
                Module module         = mm.Key;
                string moduleName     = xmlModule.Name;
                string nameSpace      = xmlModule.Namespace;
                List <Symbol> symbols = new List <Symbol>();

                foreach (var type in typeNames)
                {
                    Symbol[] foundSymbols = module.FindGlobalTypeWildcard(type.NameWildcard);

                    if (foundSymbols.Length == 0)
                    {
                        errorLogger.WriteLine("Symbol not found: {0}", type.Name);
                    }
                    else
                    {
                        symbols.AddRange(foundSymbols);
                    }
                }

                symbols.AddRange(module.GetAllTypes());
                globalTypesPerModule.TryAdd(xmlModule, symbols.ToArray());
            });

            List <Symbol> allSymbols = new List <Symbol>();

            Symbol[][] symbolsPerModule = globalTypesPerModule.Select(ss => ss.Value).ToArray();
            int        maxSymbols       = symbolsPerModule.Max(ss => ss.Length);

            for (int i = 0; i < maxSymbols; i++)
            {
                for (int j = 0; j < symbolsPerModule.Length; j++)
                {
                    if (i < symbolsPerModule[j].Length)
                    {
                        allSymbols.Add(symbolsPerModule[j][i]);
                    }
                }
            }

            logger.WriteLine(" {0}", sw.Elapsed);

#if false
            // Initialize symbol fields and base classes
            logger.Write("Initializing symbol values...");

            Parallel.ForEach(Partitioner.Create(allSymbols), (symbol) =>
            {
                var fields      = symbol.Fields;
                var baseClasses = symbol.BaseClasses;
            });

            logger.WriteLine(" {0}", sw.Elapsed);
#endif

            logger.Write("Deduplicating symbols...");

            // Group duplicated symbols
            Dictionary <string, List <Symbol> > symbolsByName     = new Dictionary <string, List <Symbol> >();
            Dictionary <Symbol, List <Symbol> > duplicatedSymbols = new Dictionary <Symbol, List <Symbol> >();

            foreach (var symbol in allSymbols)
            {
                List <Symbol> symbols;

                if (!symbolsByName.TryGetValue(symbol.Name, out symbols))
                {
                    symbolsByName.Add(symbol.Name, symbols = new List <Symbol>());
                }

                bool found = false;

                foreach (var s in symbols.ToArray())
                {
                    if (s.Size != 0 && symbol.Size != 0 && s.Size != symbol.Size)
                    {
#if DEBUG
                        logger.WriteLine("{0}!{1} ({2}) {3}!{4} ({5})", s.Module.Name, s.Name, s.Size, symbol.Module.Name, symbol.Name, symbol.Size);
#endif
                        continue;
                    }

                    if (s.Size == 0 && symbol.Size != 0)
                    {
                        List <Symbol> duplicates;

                        if (!duplicatedSymbols.TryGetValue(s, out duplicates))
                        {
                            duplicatedSymbols.Add(s, duplicates = new List <Symbol>());
                        }

                        duplicatedSymbols.Remove(s);
                        duplicates.Add(s);
                        duplicatedSymbols.Add(symbol, duplicates);
                        symbols.Remove(s);
                        symbols.Add(symbol);
                    }
                    else
                    {
                        List <Symbol> duplicates;

                        if (!duplicatedSymbols.TryGetValue(s, out duplicates))
                        {
                            duplicatedSymbols.Add(s, duplicates = new List <Symbol>());
                        }
                        duplicates.Add(symbol);
                    }

                    found = true;
                    break;
                }

                if (!found)
                {
                    symbols.Add(symbol);
                }
            }

            // Unlink duplicated symbols if two or more are named the same
            foreach (var symbols in symbolsByName.Values)
            {
                if (symbols.Count <= 1)
                {
                    continue;
                }

                foreach (var s in symbols.ToArray())
                {
                    List <Symbol> duplicates;

                    if (!duplicatedSymbols.TryGetValue(s, out duplicates))
                    {
                        continue;
                    }

                    symbols.AddRange(duplicates);
                    duplicatedSymbols.Remove(s);
                }
            }

            // Extracting deduplicated symbols
            Dictionary <string, Symbol[]> deduplicatedSymbols = new Dictionary <string, Symbol[]>();
            Dictionary <Symbol, string>   symbolNamespaces    = new Dictionary <Symbol, string>();

            foreach (var symbols in symbolsByName.Values)
            {
                if (symbols.Count != 1)
                {
                    foreach (var s in symbols)
                    {
                        symbolNamespaces.Add(s, modules[s.Module].Namespace);
                    }
                }
                else
                {
                    Symbol        symbol = symbols.First();
                    List <Symbol> duplicates;

                    if (!duplicatedSymbols.TryGetValue(symbol, out duplicates))
                    {
                        duplicates = new List <Symbol>();
                    }
                    duplicates.Insert(0, symbol);
                    deduplicatedSymbols.Add(symbol.Name, duplicates.ToArray());

                    foreach (var s in duplicates)
                    {
                        symbolNamespaces.Add(s, xmlConfig.CommonTypesNamespace);
                    }
                }
            }

            var globalTypes = symbolsByName.SelectMany(s => s.Value).ToArray();

            logger.WriteLine(" {0}", sw.Elapsed);
            logger.WriteLine("  Total symbols: {0}", globalTypesPerModule.Sum(gt => gt.Value.Length));
            logger.WriteLine("  Unique symbol names: {0}", symbolsByName.Count);
            logger.WriteLine("  Dedupedlicated symbols: {0}", globalTypes.Length);

            // Initialize GlobalCache with deduplicatedSymbols
            GlobalCache.Update(deduplicatedSymbols);

            // Collecting types
            logger.Write("Collecting types...");

            var             factory   = new UserTypeFactory(xmlConfig.Transformations);
            List <UserType> userTypes = new List <UserType>();

            foreach (var module in modules.Keys)
            {
                userTypes.Add(factory.AddSymbol(module.GlobalScope, new XmlType()
                {
                    Name = "ModuleGlobals"
                }, modules[module].Namespace, generationOptions));
            }

            ConcurrentBag <Symbol> simpleSymbols = new ConcurrentBag <Symbol>();
            Dictionary <Tuple <string, string>, List <Symbol> > templateSymbols = new Dictionary <Tuple <string, string>, List <Symbol> >();

            Parallel.ForEach(Partitioner.Create(globalTypes), (symbol) =>
            {
                string symbolName = symbol.Name;

                // TODO: Add configurable filter
                //
                if (symbolName.StartsWith("$") || symbolName.StartsWith("__vc_attributes") || symbolName.Contains("`anonymous-namespace'") || symbolName.Contains("`anonymous namespace'") || symbolName.Contains("::$") || symbolName.Contains("`"))
                {
                    return;
                }

                // Do not handle template referenced arguments
                if (symbolName.Contains("&"))
                {
                    // TODO: Convert this to function pointer
                    return;
                }

                // TODO: For now remove all unnamed-type symbols
                string scopedClassName = symbol.Namespaces.Last();

                if (scopedClassName.StartsWith("<") || symbolName.Contains("::<"))
                {
                    return;
                }

                // Check if symbol contains template type.
                if (SymbolNameHelper.ContainsTemplateType(symbolName) && symbol.Tag == SymTagEnum.SymTagUDT)
                {
                    List <string> namespaces = symbol.Namespaces;
                    string className         = namespaces.Last();
                    var symbolId             = Tuple.Create(symbolNamespaces[symbol], SymbolNameHelper.CreateLookupNameForSymbol(symbol));

                    lock (templateSymbols)
                    {
                        if (templateSymbols.ContainsKey(symbolId) == false)
                        {
                            templateSymbols[symbolId] = new List <Symbol>()
                            {
                                symbol
                            }
                        }
                        ;
                        else
                        {
                            templateSymbols[symbolId].Add(symbol);
                        }
                    }

                    // TODO:
                    // Do not add physical types for template specialization (not now)
                    // do if types contains static fields
                    // nested in templates
                }
                else
                {
                    simpleSymbols.Add(symbol);
                }
            });

            logger.WriteLine(" {0}", sw.Elapsed);

            // Populate Templates
            logger.Write("Populating templates...");
            foreach (List <Symbol> symbols in templateSymbols.Values)
            {
                Symbol symbol     = symbols.First();
                string symbolName = SymbolNameHelper.CreateLookupNameForSymbol(symbol);

                XmlType type = new XmlType()
                {
                    Name = symbolName
                };

                userTypes.AddRange(factory.AddSymbols(symbols, type, symbolNamespaces[symbol], generationOptions));
            }

            logger.WriteLine(" {0}", sw.Elapsed);

            // Specialized class
            logger.Write("Populating specialized classes...");
            foreach (Symbol symbol in simpleSymbols)
            {
                userTypes.Add(factory.AddSymbol(symbol, null, symbolNamespaces[symbol], generationOptions));
            }

            logger.WriteLine(" {0}", sw.Elapsed);

            // To solve template dependencies. Update specialization arguments once all the templates has been populated.
            logger.Write("Updating template arguments...");
            foreach (TemplateUserType templateUserType in userTypes.OfType <TemplateUserType>())
            {
                foreach (TemplateUserType specializedTemplateUserType in templateUserType.SpecializedTypes)
                {
                    if (!specializedTemplateUserType.UpdateTemplateArguments(factory))
                    {
#if DEBUG
                        logger.WriteLine("Template user type cannot be updated: {0}", specializedTemplateUserType.Symbol.Name);
#endif
                    }
                }
            }

            logger.WriteLine(" {0}", sw.Elapsed);

            // Post processing user types (filling DeclaredInType)
            logger.Write("Post processing user types...");
            var namespaceTypes = factory.ProcessTypes(userTypes, symbolNamespaces).ToArray();
            userTypes.AddRange(namespaceTypes);

            logger.WriteLine(" {0}", sw.Elapsed);

            // Code generation and saving it to disk
            logger.Write("Saving code to disk...");

            if (!generationOptions.HasFlag(UserTypeGenerationFlags.SingleFileExport))
            {
                // Generate Code
                Parallel.ForEach(userTypes,
                                 (symbolEntry) =>
                {
                    Tuple <string, string> result = GenerateCode(symbolEntry, factory, outputDirectory, errorLogger, generationOptions, generatedFiles);
                    string text     = result.Item1;
                    string filename = result.Item2;

                    if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName) && !string.IsNullOrEmpty(text))
                    {
                        lock (syntaxTrees)
                        {
                            syntaxTrees.Add(CSharpSyntaxTree.ParseText(text, path: filename, encoding: System.Text.UTF8Encoding.Default));
                        }
                    }
                });
            }
            else
            {
                string           filename = string.Format(@"{0}\everything.exported.cs", outputDirectory);
                HashSet <string> usings   = new HashSet <string>();
                foreach (var symbolEntry in userTypes)
                {
                    foreach (var u in symbolEntry.Usings)
                    {
                        usings.Add(u);
                    }
                }

                generatedFiles.TryAdd(filename.ToLowerInvariant(), filename);
                using (StringWriter stringOutput = new StringWriter())
                    using (TextWriter masterOutput = !xmlConfig.DontSaveGeneratedCodeFiles ? new StreamWriter(filename, false /* append */, System.Text.Encoding.UTF8, 16 * 1024 * 1024) : TextWriter.Null)
                    {
                        foreach (var u in usings.OrderBy(s => s))
                        {
                            masterOutput.WriteLine("using {0};", u);
                            if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName))
                            {
                                stringOutput.WriteLine("using {0};", u);
                            }
                        }
                        masterOutput.WriteLine();
                        if (xmlConfig.GenerateAssemblyWithRoslyn)
                        {
                            stringOutput.WriteLine();
                        }

                        ObjectPool <StringWriter> stringWriterPool = new ObjectPool <StringWriter>(() => new StringWriter());

                        Parallel.ForEach(userTypes,
                                         (symbolEntry) =>
                        {
                            var output = stringWriterPool.GetObject();

                            output.GetStringBuilder().Clear();
                            GenerateCodeInSingleFile(output, symbolEntry, factory, errorLogger, generationOptions);
                            string text = output.ToString();

                            if (!string.IsNullOrEmpty(text))
                            {
                                lock (masterOutput)
                                {
                                    masterOutput.WriteLine(text);
                                    if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName))
                                    {
                                        stringOutput.WriteLine(text);
                                    }
                                }
                            }

                            stringWriterPool.PutObject(output);
                        });

                        if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName))
                        {
                            syntaxTrees.Add(CSharpSyntaxTree.ParseText(stringOutput.ToString(), path: filename, encoding: UTF8Encoding.Default));
                        }
                    }
            }

            logger.WriteLine(" {0}", sw.Elapsed);

            // Compiling the code
            string binFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            if (xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName))
            {
                List <MetadataReference> references = new List <MetadataReference>
                {
                    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                    MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)
                };

                references.AddRange(xmlConfig.ReferencedAssemblies.Select(r => MetadataReference.CreateFromFile(r.Path)));

                foreach (var includedFile in includedFiles)
                {
                    syntaxTrees.Add(CSharpSyntaxTree.ParseText(File.ReadAllText(includedFile.Path), path: includedFile.Path, encoding: System.Text.UTF8Encoding.Default));
                }

                CSharpCompilation compilation = CSharpCompilation.Create(
                    Path.GetFileNameWithoutExtension(xmlConfig.GeneratedAssemblyName),
                    syntaxTrees: syntaxTrees,
                    references: references,
                    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, platform: Platform.AnyCpu));

                logger.WriteLine("Syntax trees: {0}", syntaxTrees.Count);

                string dllFilename = Path.Combine(outputDirectory, xmlConfig.GeneratedAssemblyName);
                string pdbFilename = Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(dllFilename) + ".pdb");

                using (var dllStream = new FileStream(dllFilename, FileMode.Create))
                    using (var pdbStream = new FileStream(pdbFilename, FileMode.Create))
                    {
                        var result = compilation.Emit(dllStream, !xmlConfig.DisablePdbGeneration ? pdbStream : null);

                        if (!result.Success)
                        {
                            IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                                                                                         diagnostic.IsWarningAsError ||
                                                                                         diagnostic.Severity == DiagnosticSeverity.Error);

                            errorLogger.WriteLine("Compile errors (top 1000):");
                            foreach (var diagnostic in failures.Take(1000))
                            {
                                errorLogger.WriteLine(diagnostic);
                            }
                        }
                        else
                        {
                            logger.WriteLine("DLL size: {0}", dllStream.Position);
                            logger.WriteLine("PDB size: {0}", pdbStream.Position);
                        }
                    }

                logger.WriteLine("Compiling: {0}", sw.Elapsed);
            }

            // Check whether we should generate assembly
            if (!xmlConfig.GenerateAssemblyWithRoslyn && !string.IsNullOrEmpty(xmlConfig.GeneratedAssemblyName))
            {
                var codeProvider       = new CSharpCodeProvider();
                var compilerParameters = new CompilerParameters()
                {
                    IncludeDebugInformation = !xmlConfig.DisablePdbGeneration,
                    OutputAssembly          = outputDirectory + xmlConfig.GeneratedAssemblyName,
                };

                compilerParameters.ReferencedAssemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic).Select(a => a.Location).ToArray());
                //compilerParameters.ReferencedAssemblies.AddRange(referencedAssemblies);

                const string MicrosoftCSharpDll = "Microsoft.CSharp.dll";

                if (!compilerParameters.ReferencedAssemblies.Cast <string>().Where(a => a.Contains(MicrosoftCSharpDll)).Any())
                {
                    compilerParameters.ReferencedAssemblies.Add(MicrosoftCSharpDll);
                }

                compilerParameters.ReferencedAssemblies.Add(Path.Combine(binFolder, "CsDebugScript.Engine.dll"));
                compilerParameters.ReferencedAssemblies.Add(Path.Combine(binFolder, "CsDebugScript.CommonUserTypes.dll"));

                var filesToCompile = generatedFiles.Values.Union(includedFiles.Select(f => f.Path)).ToArray();
                var compileResult  = codeProvider.CompileAssemblyFromFile(compilerParameters, filesToCompile);

                if (compileResult.Errors.Count > 0)
                {
                    errorLogger.WriteLine("Compile errors (top 1000):");
                    foreach (CompilerError err in compileResult.Errors.Cast <CompilerError>().Take(1000))
                    {
                        errorLogger.WriteLine(err);
                    }
                }

                logger.WriteLine("Compiling: {0}", sw.Elapsed);
            }

            // Generating props file
            if (!string.IsNullOrEmpty(xmlConfig.GeneratedPropsFileName))
            {
                using (TextWriter output = new StreamWriter(outputDirectory + xmlConfig.GeneratedPropsFileName, false /* append */, System.Text.Encoding.UTF8, 16 * 1024 * 1024))
                {
                    output.WriteLine(@"<?xml version=""1.0"" encoding=""utf-8""?>");
                    output.WriteLine(@"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">");
                    output.WriteLine(@"  <ItemGroup>");
                    foreach (var file in generatedFiles.Values)
                    {
                        output.WriteLine(@"    <Compile Include=""{0}"" />", file);
                    }
                    output.WriteLine(@" </ItemGroup>");
                    output.WriteLine(@"</Project>");
                }
            }

            logger.WriteLine("Total time: {0}", sw.Elapsed);
        }
예제 #7
0
 /// <summary>
 /// Writes the field code.
 /// </summary>
 /// <param name="output">The output.</param>
 /// <param name="indentation">The indentation.</param>
 /// <param name="options">The options.</param>
 public override void WriteFieldCode(IndentedWriter output, int indentation, UserTypeGenerationFlags options)
 {
     output.WriteLine(indentation, "{0} {1}();", FieldType, FieldName);
 }
예제 #8
0
 /// <summary>
 /// Generates the constructors.
 /// </summary>
 /// <param name="generationFlags">The user type generation flags.</param>
 protected override IEnumerable<UserTypeConstructor> GenerateConstructors(UserTypeGenerationFlags generationFlags)
 {
     yield return new UserTypeConstructor()
     {
         ContainsFieldDefinitions = true,
         Static = true,
     };
 }
예제 #9
0
        /// <summary>
        /// Adds the symbols to user type factory and generates the user types.
        /// </summary>
        /// <param name="symbols">The template symbols grouped around the same template type.</param>
        /// <param name="type">The XML type description.</param>
        /// <param name="nameSpace">The namespace.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <returns>Generated user types for the specified symbols.</returns>
        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.NumberOfTemplateArguments == 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.NumberOfTemplateArguments, out templates))
                            {
                                buckets.Add(templateType.NumberOfTemplateArguments, 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 (var templates 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.
                    //
                    templates.Sort((a, b) => string.Compare(a.Symbol.Name, b.Symbol.Name, StringComparison.InvariantCulture));

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

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

                        // 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 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);
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            // Declared In Type with namespace
            if (DeclaredInType != null)
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(indentation, "public static partial class {0}", innerClass);
                    output.WriteLine(indentation++, @"{{");
                }
            }
            else
            {
                output.WriteLine(indentation, "namespace {0}", Namespace);
                output.WriteLine(indentation++, @"{{");
            }

            // Inner types
            foreach (var innerType in InnerTypes)
            {
                output.WriteLine();
                innerType.WriteCode(output, error, factory, generationFlags, indentation);
            }

            // Declared In Type with namespace
            if (DeclaredInType != null)
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(--indentation, "}}");
                }
            }
            else
            {
                output.WriteLine(--indentation, "}}");
            }
        }
예제 #11
0
        /// <summary>
        /// Writes the property code to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="indentation">The current indentation.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="firstField">if set to <c>true</c> this is the first field in the user type.</param>
        public virtual void WritePropertyCode(IndentedWriter output, int indentation, UserTypeGenerationFlags generationFlags, ref bool firstField)
        {
            if (string.IsNullOrEmpty(ConstantValue))
            {
                if (generationFlags.HasFlag(UserTypeGenerationFlags.SingleLineProperty))
                {
                    if (firstField)
                    {
                        output.WriteLine();
                        firstField = false;
                    }

                    if (!UseUserMember && !CacheResult && generationFlags.HasFlag(UserTypeGenerationFlags.GenerateFieldTypeInfoComment) && !string.IsNullOrEmpty(FieldTypeInfoComment))
                    {
                        output.WriteLine(indentation, FieldTypeInfoComment);
                    }
                    if (UseUserMember && CacheResult)
                    {
                        output.WriteLine(indentation, "public {0}{1} {2} {{ get {{ return {3}.Value; }} }}", Static ? "static " : "", FieldType, PropertyName, FieldName);
                    }
                    else if (CacheResult)
                    {
                        output.WriteLine(indentation, "public {0}{1} {2} {{ get {{ return {3}; }} }}", Static ? "static " : "", FieldType, PropertyName, FieldName);
                    }
                    else
                    {
                        output.WriteLine(indentation, "public {0}{1} {2} {{ get {{ return {3}; }} }}", Static ? "static " : "", FieldType, PropertyName, ConstructorText);
                    }
                }
                else
                {
                    output.WriteLine();
                    if (!UseUserMember && !CacheResult && generationFlags.HasFlag(UserTypeGenerationFlags.GenerateFieldTypeInfoComment) && !string.IsNullOrEmpty(FieldTypeInfoComment))
                    {
                        output.WriteLine(indentation, FieldTypeInfoComment);
                    }
                    output.WriteLine(indentation, "public {0}{1} {2}", Static ? "static " : "", FieldType, PropertyName);
                    output.WriteLine(indentation++, "{{");
                    output.WriteLine(indentation, "get");
                    output.WriteLine(indentation++, "{{");
                    if (UseUserMember && CacheResult)
                    {
                        output.WriteLine(indentation, "return {0}.Value;", FieldName);
                    }
                    else if (CacheResult)
                    {
                        output.WriteLine(indentation, "return {0};", FieldName);
                    }
                    else
                    {
                        output.WriteLine(indentation, "return {0};", ConstructorText);
                    }
                    output.WriteLine(--indentation, "}}");
                    output.WriteLine(--indentation, "}}");
                }
            }
        }
예제 #12
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            string[] namespaces = this.namespaces;

            if (generationFlags.HasFlag(UserTypeGenerationFlags.GenerateNamespaceAsStaticClass))
            {
                namespaces = NamespaceSymbol.Split(".".ToCharArray());
            }

            // Declared In Type with namespace
            if (DeclaredInType != null || generationFlags.HasFlag(UserTypeGenerationFlags.GenerateNamespaceAsStaticClass))
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(indentation, "public static partial class {0}", innerClass);
                    output.WriteLine(indentation++, @"{{");
                }
            }
            else
            {
                output.WriteLine(indentation, "namespace {0}", Namespace);
                output.WriteLine(indentation++, @"{{");
            }

            // Inner types
            foreach (var innerType in InnerTypes)
            {
                output.WriteLine();
                innerType.WriteCode(output, error, factory, generationFlags, indentation);
            }

            // Declared In Type with namespace
            if (DeclaredInType != null || generationFlags.HasFlag(UserTypeGenerationFlags.GenerateNamespaceAsStaticClass))
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(--indentation, "}}");
                }
            }
            else
            {
                output.WriteLine(--indentation, "}}");
            }
        }
예제 #13
0
        /// <summary>
        /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function.
        /// Do not use this function directly, unless you are calling it from overridden function.
        /// </summary>
        /// <param name="field">The symbol field.</param>
        /// <param name="fieldType">The field tree type.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param>
        /// <param name="gettingField">The code for getting field variable.</param>
        /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass)
        {
            // Physical code generation make sense only for non-static fields
            if (!isStatic)
            {
                bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields);

                bool                   cacheUserTypeFields       = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields);
                bool                   cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields);
                string                 constructorText           = "";
                string                 fieldName          = field.Name;
                string                 fieldTypeString    = fieldType.GetTypeString();
                BasicTypeTree          baseType           = fieldType as BasicTypeTree;
                ArrayTypeTree          codeArrayType      = fieldType as ArrayTypeTree;
                UserTypeTree           userType           = fieldType as UserTypeTree;
                TransformationTypeTree transformationType = fieldType as TransformationTypeTree;
                bool                   isEmbedded         = field.Type.Tag != CodeTypeTag.Pointer;

                // Specialization for basic types
                if (baseType != null)
                {
                    if (baseType.BasicType == "string")
                    {
                        int charSize = field.Type.ElementType.Size;

                        constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize);
                    }
                    else if (baseType.BasicType != "NakedPointer")
                    {
                        if (field.LocationType == LocationType.BitField)
                        {
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition);
                        }
                        else
                        {
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset);
                        }
                    }
                }
                // Specialization for arrays
                else if (codeArrayType != null)
                {
                    if (codeArrayType.ElementType is BasicTypeTree)
                    {
                        baseType = (BasicTypeTree)codeArrayType.ElementType;
                        if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer")
                        {
                            int arraySize   = field.Type.Size;
                            int elementSize = field.Type.ElementType.Size;

                            if (baseType.BasicType == "char")
                            {
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize);
                            }
                            else
                            {
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize);
                            }
                            fieldTypeString = baseType.GetTypeString() + "[]";
                        }
                    }
                }
                // Specialization for user types
                else if (userType != null && !extractingBaseClass)
                {
                    if (!(userType.UserType is EnumUserType))
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                        {
                            thisClassCodeType = ClassCodeType;
                        }
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass     = true;
                        }

                        // Check if type is embedded
                        if (!isEmbedded)
                        {
                            // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly
                            if (IsTypeUsingStaticCodeType(this))
                            {
                                constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType);
                            }
                            else
                            {
                                constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size);
                                usedThisClass   = true;
                            }

                            // Do downcasting if field has vtable
                            if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0)
                            {
                                constructorText += ".DowncastObject()";
                            }
                        }
                        else
                        {
                            // If user type is embedded, we can reuse memory buffer that we already have in this class
                            string fieldAddress  = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                            string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName);

                            if (IsTypeUsingStaticCodeType(userType.UserType))
                            {
                                fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType);
                            }
                            else if (IsTypeUsingStaticCodeType(this))
                            {
                                fieldCodeType = AddFieldCodeType(fieldName);
                            }

                            constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName);
                        }
                    }
                    else
                    {
                        // TODO: This is enum. Read how much enum base type is big and just cast to enum type...
                    }
                }
                // Specialization for transformations
                else if (transformationType != null)
                {
                    if (!isEmbedded)
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                        {
                            thisClassCodeType = ClassCodeType;
                        }
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass     = true;
                        }

                        string fieldAddress  = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                        string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress);

                        if (transformationType.Transformation.Transformation.HasPhysicalConstructor)
                        {
                            fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset);
                        }

                        simpleFieldValue = fieldVariable;
                        constructorText  = string.Format("new {0}({1})", fieldTypeString, fieldVariable);
                    }
                }

                // If we found suitable physical representation, generate the field
                if (!string.IsNullOrEmpty(constructorText))
                {
                    return new UserTypeField()
                           {
                               ConstructorText      = constructorText,
                               FieldName            = "_" + fieldName,
                               FieldType            = fieldTypeString,
                               FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName),
                               PropertyName         = UserTypeField.GetPropertyName(field, this),
                               Static           = isStatic,
                               UseUserMember    = lazyCacheUserTypeFields,
                               CacheResult      = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields),
                               SimpleFieldValue = simpleFieldValue,
                           }
                }
                ;
            }

            return(base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass));
        }
예제 #14
0
        /// <summary>
        /// Generates the code for user type in single file.
        /// </summary>
        /// <param name="output">The output text writer.</param>
        /// <param name="userType">The user type.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="errorOutput">The error output.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <returns><c>true</c> if code was generated for the type; otherwise <c>false</c></returns>
        private static bool GenerateCodeInSingleFile(TextWriter output, UserType userType, UserTypeFactory factory, TextWriter errorOutput, UserTypeGenerationFlags generationFlags)
        {
            Symbol symbol = userType.Symbol;

            if (symbol != null && symbol.Tag == SymTagEnum.SymTagBaseType)
            {
                // ignore Base (Primitive) types.
                return(false);
            }

            if (userType.DeclaredInType != null)
            {
                return(false);
            }

            userType.WriteCode(new IndentedWriter(output, generationFlags.HasFlag(UserTypeGenerationFlags.CompressedOutput)), errorOutput, factory, generationFlags);
            return(true);
        }
예제 #15
0
        /// <summary>
        /// Generates the code for user type and creates a file for it.
        /// </summary>
        /// <param name="userType">The user type.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="outputDirectory">The output directory where code file will be stored.</param>
        /// <param name="errorOutput">The error output.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="generatedFiles">The list of already generated files.</param>
        /// <returns>Tuple of generated code and filename</returns>
        private static Tuple <string, string> GenerateCode(UserType userType, UserTypeFactory factory, string outputDirectory, TextWriter errorOutput, UserTypeGenerationFlags generationFlags, ConcurrentDictionary <string, string> generatedFiles)
        {
            Symbol symbol = userType.Symbol;

            if (symbol != null && symbol.Tag == SymTagEnum.SymTagBaseType)
            {
                // ignore Base (Primitive) types.
                return(Tuple.Create("", ""));
            }

            bool allParentsAreNamespaces = true;

            for (UserType parentType = userType.DeclaredInType; parentType != null && allParentsAreNamespaces; parentType = parentType.DeclaredInType)
            {
                allParentsAreNamespaces = parentType is NamespaceUserType;
            }

            if (userType is NamespaceUserType || !allParentsAreNamespaces)
            {
                return(Tuple.Create("", ""));
            }

            string classOutputDirectory = outputDirectory;
            string nameSpace            = (userType.DeclaredInType as NamespaceUserType)?.FullClassName ?? userType.Namespace;

            if (!string.IsNullOrEmpty(nameSpace))
            {
                classOutputDirectory = Path.Combine(classOutputDirectory, nameSpace.Replace(".", "\\").Replace(":", "."));
            }
            Directory.CreateDirectory(classOutputDirectory);

            bool isEnum = userType is EnumUserType;

            string filename = string.Format(@"{0}\{1}{2}.exported.cs", classOutputDirectory, userType.ConstructorName, isEnum ? "_enum" : "");

            int index = 1;

            while (true)
            {
                if (generatedFiles.TryAdd(filename.ToLowerInvariant(), filename))
                {
                    break;
                }

                filename = string.Format(@"{0}\{1}{2}_{3}.exported.cs", classOutputDirectory, userType.ConstructorName, isEnum ? "_enum" : "", index++);
            }

            using (TextWriter output = new StreamWriter(filename))
                using (StringWriter stringOutput = new StringWriter())
                {
                    userType.WriteCode(new IndentedWriter(stringOutput, generationFlags.HasFlag(UserTypeGenerationFlags.CompressedOutput)), errorOutput, factory, generationFlags);
                    string text = stringOutput.ToString();
                    output.WriteLine(text);
                    return(Tuple.Create(text, filename));
                }
        }
예제 #16
0
        /// <summary>
        /// Generates the constructors.
        /// </summary>
        /// <param name="generationFlags">The user type generation flags.</param>
        protected override IEnumerable<UserTypeConstructor> GenerateConstructors(UserTypeGenerationFlags generationFlags)
        {
            yield return new UserTypeConstructor()
            {
                ContainsFieldDefinitions = true,
                Static = true,
            };

            yield return new UserTypeConstructor()
            {
                Arguments = "Variable variable",
                BaseClassInitialization = string.Format("this(variable.GetBaseClass(baseClassString), Debugger.ReadMemory(variable.GetCodeType().Module.Process, variable.GetBaseClass(baseClassString).GetPointerAddress(), {0}), 0, variable.GetBaseClass(baseClassString).GetPointerAddress())", Symbol.Size),
                ContainsFieldDefinitions = false,
                Static = false,
            };

            yield return new UserTypeConstructor()
            {
                Arguments = "Variable variable, CsDebugScript.Engine.Utility.MemoryBuffer buffer, int offset, ulong bufferAddress",
                BaseClassInitialization = string.Format("base(variable, buffer, offset{0}, bufferAddress)", baseClassOffset > 0 ? " + " + baseClassOffset : ""),
                ContainsFieldDefinitions = true,
                Static = false,
            };

            yield return new UserTypeConstructor()
            {
                Arguments = "CsDebugScript.Engine.Utility.MemoryBuffer buffer, int offset, ulong bufferAddress, CodeType codeType, ulong address, string name = Variable.ComputedName, string path = Variable.UnknownPath",
                BaseClassInitialization = string.Format("base(buffer, offset{0}, bufferAddress, codeType, address, name, path)", baseClassOffset > 0 ? " + " + baseClassOffset : ""),
                ContainsFieldDefinitions = true,
                Static = false,
            };
        }
예제 #17
0
        /// <summary>
        /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function.
        /// Do not use this function directly, unless you are calling it from overridden function.
        /// </summary>
        /// <param name="field">The symbol field.</param>
        /// <param name="fieldType">The field tree type.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param>
        /// <param name="gettingField">The code for getting field variable.</param>
        /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass)
        {
            // Physical code generation make sense only for non-static fields
            if (!isStatic)
            {
                bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields);
                bool cacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields);
                bool cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields);
                string constructorText = "";
                string fieldName = field.Name;
                string fieldTypeString = fieldType.GetTypeString();
                BasicTypeTree baseType = fieldType as BasicTypeTree;
                ArrayTypeTree codeArrayType = fieldType as ArrayTypeTree;
                UserTypeTree userType = fieldType as UserTypeTree;
                TransformationTypeTree transformationType = fieldType as TransformationTypeTree;
                bool isEmbedded = field.Type.Tag != SymTagEnum.SymTagPointerType;

                // Specialization for basic types
                if (baseType != null)
                {
                    if (baseType.BasicType == "string")
                    {
                        int charSize = field.Type.ElementType.Size;

                        constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize);
                    }
                    else if (baseType.BasicType != "NakedPointer")
                    {
                        if (field.LocationType == LocationType.BitField)
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition);
                        else
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset);
                    }
                }
                // Specialization for arrays
                else if (codeArrayType != null)
                {
                    if (codeArrayType.ElementType is BasicTypeTree)
                    {
                        baseType = (BasicTypeTree)codeArrayType.ElementType;
                        if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer")
                        {
                            int arraySize = field.Type.Size;
                            int elementSize = field.Type.ElementType.Size;

                            if (baseType.BasicType == "char")
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize);
                            else
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize);
                            fieldTypeString = baseType.GetTypeString() + "[]";
                        }
                    }
                }
                // Specialization for user types
                else if (userType != null && !extractingBaseClass)
                {
                    if (!(userType.UserType is EnumUserType))
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                            thisClassCodeType = ClassCodeType;
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass = true;
                        }

                        // Check if type is embedded
                        if (!isEmbedded)
                        {
                            // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly
                            if (IsTypeUsingStaticCodeType(this))
                                constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType);
                            else
                            {
                                constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size);
                                usedThisClass = true;
                            }

                            // Do downcasting if field has vtable
                            if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0)
                                constructorText += ".DowncastObject()";
                        }
                        else
                        {
                            // If user type is embedded, we can reuse memory buffer that we already have in this class
                            string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                            string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName);

                            if (IsTypeUsingStaticCodeType(userType.UserType))
                            {
                                fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType);
                            }
                            else if (IsTypeUsingStaticCodeType(this))
                            {
                                fieldCodeType = AddFieldCodeType(fieldName);
                            }

                            constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName);
                        }
                    }
                    else
                    {
                        // TODO: This is enum. Read how much enum base type is big and just cast to enum type...
                    }
                }
                // Specialization for transformations
                else if (transformationType != null)
                {
                    if (!isEmbedded)
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                            thisClassCodeType = ClassCodeType;
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass = true;
                        }

                        string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                        string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress);

                        if (transformationType.Transformation.Transformation.HasPhysicalConstructor)
                        {
                            fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset);
                        }

                        simpleFieldValue = fieldVariable;
                        constructorText = string.Format("new {0}({1})", fieldTypeString, fieldVariable);
                    }
                }

                // If we found suitable physical representation, generate the field
                if (!string.IsNullOrEmpty(constructorText))
                    return new UserTypeField()
                    {
                        ConstructorText = constructorText,
                        FieldName = "_" + fieldName,
                        FieldType = fieldTypeString,
                        FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName),
                        PropertyName = UserTypeField.GetPropertyName(fieldName, this),
                        Static = isStatic,
                        UseUserMember = lazyCacheUserTypeFields,
                        CacheResult = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields),
                        SimpleFieldValue = simpleFieldValue,
                    };
            }

            return base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass);
        }
예제 #18
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            // Check if we need to write namespace
            string nameSpace     = (DeclaredInType as NamespaceUserType)?.FullClassName ?? Namespace;
            string enumBasicType = GetEnumBasicType(Symbol);

            if ((DeclaredInType == null || (!generationFlags.HasFlag(UserTypeGenerationFlags.SingleFileExport) && DeclaredInType is NamespaceUserType)) && !string.IsNullOrEmpty(nameSpace))
            {
                output.WriteLine(indentation, "namespace {0}", nameSpace);
                output.WriteLine(indentation++, "{{");
            }

            // Write beginning of the enumeration
            if (generationFlags.HasFlag(UserTypeGenerationFlags.GenerateFieldTypeInfoComment))
            {
                output.WriteLine(indentation, "// {0} (original name: {1})", ClassName, Symbol.Name);
            }

            if (AreValuesFlags())
            {
                output.WriteLine(indentation, @"[System.Flags]");
            }
            if (Symbol.Size != 0)
            {
                output.WriteLine(indentation, @"public enum {0} : {1}", ClassName, enumBasicType);
            }
            else
            {
                output.WriteLine(indentation, @"public enum {0}", ClassName);
            }
            output.WriteLine(indentation++, @"{{");

            // Write values
            foreach (var enumValue in Symbol.EnumValues)
            {
                string value = enumValue.Item2;

                if (!FitsBasicType(enumBasicType, ref value))
                {
                    output.WriteLine(indentation, "{0} = ({1}){2},", enumValue.Item1, enumBasicType, value);
                }
                else
                {
                    output.WriteLine(indentation, "{0} = {1},", enumValue.Item1, value);
                }
            }

            // Enumeration end
            output.WriteLine(--indentation, @"}}");
            if ((DeclaredInType == null || (!generationFlags.HasFlag(UserTypeGenerationFlags.SingleFileExport) && DeclaredInType is NamespaceUserType)) && !string.IsNullOrEmpty(nameSpace))
            {
                output.WriteLine(--indentation, "}}");
            }
        }
예제 #19
0
        /// <summary>
        /// Gets the user type generation flags.
        /// </summary>
        internal UserTypeGenerationFlags GetGenerationFlags()
        {
            UserTypeGenerationFlags generationFlags = UserTypeGenerationFlags.None;

            if (CompressedOutput)
            {
                generationFlags |= UserTypeGenerationFlags.CompressedOutput;
                DontGenerateFieldTypeInfoComment = true;
                MultiLineProperties = false;
            }

            if (!DontGenerateFieldTypeInfoComment)
            {
                generationFlags |= UserTypeGenerationFlags.GenerateFieldTypeInfoComment;
            }
            if (!MultiLineProperties)
            {
                generationFlags |= UserTypeGenerationFlags.SingleLineProperty;
            }
            if (UseDirectClassAccess)
            {
                generationFlags |= UserTypeGenerationFlags.UseDirectClassAccess;
            }
            if (ForceUserTypesToNewInsteadOfCasting)
            {
                generationFlags |= UserTypeGenerationFlags.ForceUserTypesToNewInsteadOfCasting;
            }
            if (CacheUserTypeFields)
            {
                generationFlags |= UserTypeGenerationFlags.CacheUserTypeFields;
            }
            if (CacheStaticUserTypeFields)
            {
                generationFlags |= UserTypeGenerationFlags.CacheStaticUserTypeFields;
            }
            if (LazyCacheUserTypeFields)
            {
                generationFlags |= UserTypeGenerationFlags.LazyCacheUserTypeFields;
            }
            if (GeneratePhysicalMappingOfUserTypes)
            {
                generationFlags |= UserTypeGenerationFlags.GeneratePhysicalMappingOfUserTypes;
            }
            if (!MultiFileExport)
            {
                generationFlags |= UserTypeGenerationFlags.SingleFileExport;
            }
            if (UseHungarianNotation)
            {
                generationFlags |= UserTypeGenerationFlags.UseHungarianNotation;
            }
            if (GenerateNamespaceAsStaticClass)
            {
                generationFlags |= UserTypeGenerationFlags.GenerateNamespaceAsStaticClass;
            }
            if (DontSaveGeneratedCodeFiles && GenerateAssemblyWithRoslyn)
            {
                generationFlags |= UserTypeGenerationFlags.DontSaveGeneratedCodeFiles;
            }
            if (InitializeSymbolCaches)
            {
                generationFlags |= UserTypeGenerationFlags.InitializeSymbolCaches;
            }
            return(generationFlags);
        }
예제 #20
0
        /// <summary>
        /// Extracts all fields from the user type.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        protected override IEnumerable <UserTypeField> ExtractFields(UserTypeFactory factory, UserTypeGenerationFlags generationFlags)
        {
            ExportStaticFields = true;

            var    fields       = Symbol.Fields.OrderBy(s => s.Name).ToArray();
            bool   useThisClass = generationFlags.HasFlag(UserTypeGenerationFlags.UseClassFieldsFromDiaSymbolProvider);
            string previousName = "";

            foreach (var field in fields)
            {
                if (string.IsNullOrEmpty(field.Type.Name))
                {
                    continue;
                }

                if (IsFieldFiltered(field) || field.Name == previousName)
                {
                    continue;
                }

                if (field.Name.Contains("@"))
                {
                    // Skip names contaings '@'
                    continue;
                }

                // Skip fields that are actual values of enum values
                if (field.Type.Tag == Dia2Lib.SymTagEnum.SymTagEnum && field.Type.GetEnumValues().Any(t => t.Item1 == field.Name))
                {
                    continue;
                }

                var userField = ExtractField(field, factory, generationFlags, forceIsStatic: true);

                if (field.Type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType)
                {
                    // Do not use const values for pointers.
                    // We do not allow user type implicit conversion from integers.
                    userField.ConstantValue = string.Empty;
                }

                userField.FieldName    = NormalizeSymbolNamespace(userField.FieldName);
                userField.PropertyName = NormalizeSymbolNamespace(userField.PropertyName);

                yield return(userField);

                previousName = field.Name;
            }

            foreach (var field in GetAutoGeneratedFields(false, useThisClass))
            {
                yield return(field);
            }
        }
예제 #21
0
 /// <summary>
 /// Writes the property code.
 /// </summary>
 /// <param name="output">The output.</param>
 /// <param name="indentation">The indentation.</param>
 /// <param name="options">The options.</param>
 /// <param name="firstField">if set to <c>true</c> [first field].</param>
 public override void WritePropertyCode(IndentedWriter output, int indentation, UserTypeGenerationFlags options, ref bool firstField)
 {
     // Do nothing
 }
예제 #22
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DotNetCodeWriter"/> class.
 /// </summary>
 /// <param name="generationFlags">The code generation options</param>
 /// <param name="nameLimit">Maximum number of characters that generated name can have.</param>
 /// <param name="fixKeywordsInUserNaming">Should we fix keywords by adding @ when fixing user naming?</param>
 public DotNetCodeWriter(UserTypeGenerationFlags generationFlags, int nameLimit, bool fixKeywordsInUserNaming)
 {
     GenerationFlags         = generationFlags;
     NameLimit               = nameLimit;
     FixKeywordsInUserNaming = fixKeywordsInUserNaming;
 }
예제 #23
0
        /// <summary>
        /// Writes the code for this user type to the specified output.
        /// </summary>
        /// <param name="output">The output.</param>
        /// <param name="error">The error text writer.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="indentation">The current indentation.</param>
        public override void WriteCode(IndentedWriter output, TextWriter error, UserTypeFactory factory, UserTypeGenerationFlags generationFlags, int indentation = 0)
        {
            // Declared In Type with namespace
            if (DeclaredInType != null)
            {
                foreach (string innerClass in namespaces)
                {
                    output.WriteLine(indentation, "public static partial class {0}", innerClass);
                    output.WriteLine(indentation++, @"{{");
                }
            }
            else
            {
                output.WriteLine(indentation, "namespace {0}", Namespace);
                output.WriteLine(indentation++, @"{{");
            }

            // Inner types
            foreach (var innerType in InnerTypes)
            {
                output.WriteLine();
                innerType.WriteCode(output, error, factory, generationFlags, indentation);
            }

            // Declared In Type with namespace
            if (DeclaredInType != null)
                foreach (string innerClass in namespaces)
                    output.WriteLine(--indentation, "}}");
            else
                output.WriteLine(--indentation, "}}");
        }
예제 #24
0
        /// <summary>
        /// Extracts all fields from the user type.
        /// </summary>
        /// <param name="factory">The user type factory.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        protected override IEnumerable <UserTypeField> ExtractFields(UserTypeFactory factory, UserTypeGenerationFlags generationFlags)
        {
            ExportStaticFields = true;

            var              fields       = Symbol.Fields.OrderBy(s => s.Name).ToArray();
            bool             useThisClass = generationFlags.HasFlag(UserTypeGenerationFlags.UseDirectClassAccess);
            HashSet <string> usedNames    = new HashSet <string>();

            foreach (var field in fields)
            {
                if (string.IsNullOrEmpty(field.Type.Name))
                {
                    continue;
                }

                if (IsFieldFiltered(field))
                {
                    continue;
                }

                field.PropertyName = NormalizeSymbolNamespace(UserTypeField.GetPropertyName(field, this));
                while (usedNames.Contains(field.PropertyName))
                {
                    field.PropertyName += "_";
                }

                if (field.Name.Contains("@") || field.PropertyName.Length > 511)
                {
                    // Skip names containing '@'
                    continue;
                }

                // Skip fields that are actual values of enum values
                if (field.Type.Tag == CodeTypeTag.Enum && field.Type.EnumValues.Any(t => t.Item1 == field.Name))
                {
                    continue;
                }

                var userField = ExtractField(field, factory, generationFlags, forceIsStatic: true);

                if (field.Type.Tag == CodeTypeTag.Pointer)
                {
                    // Do not use const values for pointers.
                    // We do not allow user type implicit conversion from integers.
                    userField.ConstantValue = string.Empty;
                }

                userField.FieldName    = NormalizeSymbolNamespace(userField.FieldName);
                userField.PropertyName = NormalizeSymbolNamespace(userField.PropertyName);

                yield return(userField);

                usedNames.Add(field.PropertyName);
            }

            foreach (var field in GetAutoGeneratedFields(false, useThisClass))
            {
                yield return(field);
            }
        }