예제 #1
0
        public static CGFFieldSymbol Parse(CGFParserReporter reporter, Microsoft.CodeAnalysis.IFieldSymbol fieldSymbol)
        {
            CGFFieldSymbol cgfFieldSymbol = new CGFFieldSymbol(fieldSymbol);

            cgfFieldSymbol.m_AttributeDataList = CGFAttributeDataList.Parse(reporter, fieldSymbol.GetAttributes());

            return(cgfFieldSymbol);
        }
예제 #2
0
        static ExitCode ProcessSolution(string solutionPath)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();

            CGFParserReporter reporter       = new CGFParserReporter();
            CGFParser         solutionParser = CGFParser.ParseSolution(reporter, solutionPath);

            if (solutionParser == null)
            {
                return(ExitCode.GenerationError);
            }

            reporter.LogInfo("Generating code");
            foreach (CGFDocument cgfDocument in solutionParser.Documents)
            {
                string sourcePath = cgfDocument.DocumentFilePath;

                const string sourceString             = "source";
                const string generatedString          = "generated";
                string       generatedPath            = ReplaceFolderInPath(sourcePath, sourceString, generatedString);
                bool         hasResolvedGeneratedPath = !generatedPath.Equals(sourcePath);

                if (!hasResolvedGeneratedPath)
                {
                    generatedPath = Path.Combine(generatedPath, "CGFGenerated");
                    reporter.LogWarning($"Failed to find {sourceString} in {sourcePath} to replace with {generatedString}. Writing generated files to Appending {generatedPath}.");
                }

                string headerPath = generatedPath.Replace(".cs", ".h");
                string inlinePath = generatedPath.Replace(".cs", ".inl");
                string relativeInlinePath;
                if (hasResolvedGeneratedPath)
                {
                    relativeInlinePath = inlinePath.Substring(inlinePath.LastIndexOf(generatedString) + generatedString.Length + 1); //1 is for path separator
                }
                else
                {
                    relativeInlinePath = Path.GetFileName(inlinePath);
                }

                string userPath         = sourcePath.Replace(".cs", ".user.inl");
                string relativeUserPath = GetRelativePath(userPath, sourceString);

                //Get System Includes
                HashSet <string> systemIncludes = new HashSet <string>();
                systemIncludes.Add("iostream"); //Always need iostream for istream/ostream

                //Get User includes
                HashSet <string> userIncludes = new HashSet <string>();
                foreach (CGFTypeSymbol type in cgfDocument.Types)
                {
                    foreach (CGFFieldSymbol field in type.Fields)
                    {
                        CGFAttributeDataList fieldAttributes = field.Attributes;
                        ArrayAttribute       arrayAttribute  = fieldAttributes.GetAttribute <ArrayAttribute>();
                        if (arrayAttribute != null)
                        {
                            foreach (ArrayDimension dimension in arrayAttribute.Dimensions)
                            {
                                systemIncludes.Add(dimension.LibraryName);
                            }
                        }

                        if (field.IsSystemType && field.UnderlyingSpecialType == SpecialType.System_String)
                        {
                            systemIncludes.Add("string");
                        }

                        string typePath = null;
                        if (solutionParser.TypeNameToPathMap.TryGetValue(field.TypeName, out typePath))
                        {
                            if (typePath != cgfDocument.DocumentFilePath)
                            {
                                string relativeTypePath = GetRelativePath(typePath, sourceString);
                                userIncludes.Add(relativeTypePath.Replace(".cs", ".h").Replace("\\", "/"));
                            }
                        }
                    }
                }

                CGFHeaderCodeGenerator headerCodeGenerator = new CGFHeaderCodeGenerator(cgfDocument, relativeInlinePath, relativeUserPath, systemIncludes, userIncludes);
                CGFInlineCodeGenerator inlineCodeGenerator = new CGFInlineCodeGenerator(cgfDocument);
                CGFUserCodeGenerator   userCodeGenerator   = new CGFUserCodeGenerator(cgfDocument);

                string headerCode = headerCodeGenerator.TransformText();
                string inlineCode = inlineCodeGenerator.TransformText();
                string userCode   = userCodeGenerator.TransformText();

                WriteFile(headerPath, headerCode);
                WriteFile(inlinePath, inlineCode);
                WriteUserFile(userPath, userCode, reporter);
            }

            long elapsedMS = stopwatch.ElapsedMilliseconds;

            reporter.LogInfo(String.Format("Code generation done in {0:0.0} sec", elapsedMS / 1000.0f));

            if (reporter.HasError())
            {
                reporter.LogError("Code generation failed with errors");
                return(ExitCode.GenerationError);
            }
            else
            {
                reporter.LogInfo("Code generated");
                return(ExitCode.Success);
            }
        }
예제 #3
0
        static void WriteUserFile(string filepath, string fileContents, CGFParserReporter reporter)
        {
            if (!File.Exists(filepath))
            {
                string directory = Path.GetDirectoryName(filepath);
                Directory.CreateDirectory(directory);

                string newFileContents = GenerateUserFileWithHash(filepath, fileContents);
                File.WriteAllText(filepath, newFileContents);
            }
            else
            {
                //Get previous file hash
                string[] existingFileStrings = File.ReadAllLines(filepath, Encoding.UTF8);

                if (existingFileStrings.Length < 2)
                {
                    reporter.LogWarning(filepath + " has unexpected content. This file will not be modified. To have it automatically regenerated delete the file and rerun the code generator.");
                    return;
                }

                if (!existingFileStrings[1].StartsWith(UserFileHashTag))
                {
                    reporter.LogWarning(filepath + " has unexpected content. This file will not be modified. To have it automatically regenerated delete the file and rerun the code generator.");
                    return;
                }

                string existingFileHash = existingFileStrings[1].Substring(UserFileHashTag.Length);

                //Calculate previous file hash
                StringBuilder existingFileNoHashBuilder = new StringBuilder();
                for (int i = 2; i < existingFileStrings.Length; i++)
                {
                    existingFileNoHashBuilder.Append(existingFileStrings[i]);
                    existingFileNoHashBuilder.Append(System.Environment.NewLine);
                }
                string existingFileContentsNoHash = existingFileNoHashBuilder.ToString();
                string calculatedHash             = ComputeHashString(existingFileContentsNoHash);

                if (calculatedHash != existingFileHash)
                {
                    reporter.LogInfo(filepath + " has a hash that does not match the calculated file hash. This likely means it was modified by hand. This file will not be modified. To have it automatically regenerated delete the file and rerun the code generator.");
                    return;
                }

                //Create one string with the contents of the existingFile
                StringBuilder existingFileBuilder = new StringBuilder();
                for (int i = 0; i < existingFileStrings.Length; i++)
                {
                    existingFileBuilder.Append(existingFileStrings[i]);
                    existingFileBuilder.Append(System.Environment.NewLine);
                }
                string existingFileContents = existingFileBuilder.ToString();

                //Create string for new contents
                string newFileContents = GenerateUserFileWithHash(filepath, fileContents);

                //Only write file if contents are different
                if (existingFileContents != newFileContents)
                {
                    File.WriteAllText(filepath, newFileContents);
                }
            }
        }