Beispiel #1
0
        private static string GetMessageAndLocation(string rootContent, CXDiagnostic diagnostic, out CppSourceLocation location)
        {
            var builder = new StringBuilder();

            builder.Append(diagnostic.ToString());
            location = CppModelBuilder.GetSourceLocation(diagnostic.Location);
            if (location.File == CppAstRootFileName)
            {
                var    reader = new StringReader(rootContent);
                var    lines  = new List <string>();
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    lines.Add(line);
                }

                var lineIndex = location.Line - 1;
                if (lineIndex < lines.Count)
                {
                    builder.AppendLine();
                    builder.AppendLine(lines[lineIndex]);
                    for (int i = 0; i < location.Column - 1; i++)
                    {
                        builder.Append(i + 1 == location.Column - 1 ? "-" : " ");
                    }

                    builder.AppendLine("^-");
                }
            }

            return(builder.ToString());
        }
Beispiel #2
0
        /// <summary>
        /// Private method parsing file or content.
        /// </summary>
        /// <param name="cppFiles">A list of path to C/C++ header files on the disk to parse</param>
        /// <param name="options">Options used for parsing this file (e.g include folders...)</param>
        /// <returns>The result of the compilation</returns>
        private static CppCompilation ParseInternal(List <CppFileOrString> cppFiles, CppParserOptions options = null)
        {
            if (cppFiles == null)
            {
                throw new ArgumentNullException(nameof(cppFiles));
            }

            options = options ?? new CppParserOptions();

            var arguments = new List <string>();

            // Make sure that paths are absolute
            var normalizedIncludePaths = new List <string>();

            normalizedIncludePaths.AddRange(options.IncludeFolders.Select(x => Path.Combine(Environment.CurrentDirectory, x)));

            arguments.AddRange(options.AdditionalArguments);
            arguments.AddRange(normalizedIncludePaths.Select(x => $"-I{x}"));
            arguments.AddRange(options.Defines.Select(x => $"-D{x}"));

            if (options.ParseAsCpp && !arguments.Contains("-xc++"))
            {
                arguments.Add("-xc++");
            }

            if (!arguments.Any(x => x.StartsWith("--target=")))
            {
                arguments.Add($"--target={GetTripleFromOptions(options)}");
            }

            if (options.ParseComments)
            {
                arguments.Add("-fparse-all-comments");
            }

            var translationFlags = CXTranslationUnit_Flags.CXTranslationUnit_None;

            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies;                   // Don't traverse function bodies
            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes;               // Include attributed types in CXType
            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes;              // Implicit attributes should be visited

            if (options.ParseMacros)
            {
                translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord;
            }

            var argumentsArray = arguments.ToArray();

            using (var createIndex = CXIndex.Create())
            {
                var builder = new CppModelBuilder {
                    AutoSquashTypedef = options.AutoSquashTypedef
                };
                var compilation = builder.RootCompilation;

                var writeToTemp = cppFiles.All(f => f.Content == null);

                string rootFileName    = null;
                string rootFileContent = null;

                if (writeToTemp)
                {
                    var tempFileName = Path.GetTempFileName() + "_cppast.h";
                    var tempBuilder  = new StringBuilder();
                    foreach (var file in cppFiles)
                    {
                        var filePath = Path.Combine(Environment.CurrentDirectory, file.Filename);
                        tempBuilder.AppendLine($"#include \"{filePath}\"");
                    }
                    File.WriteAllText(tempFileName, tempBuilder.ToString());
                    rootFileName = tempFileName;
                }
                else
                {
                    rootFileName    = cppFiles[0].Filename ?? "content";
                    rootFileContent = cppFiles[0].Content;
                }

                {
                    CXTranslationUnit translationUnit;
                    CXErrorCode       translationUnitError;

                    if (rootFileContent == null)
                    {
                        translationUnitError = CXTranslationUnit.Parse(createIndex, rootFileName, argumentsArray, Array.Empty <CXUnsavedFile>(), translationFlags, out translationUnit);
                    }
                    else
                    {
                        translationUnitError = CXTranslationUnit.Parse(createIndex, rootFileName, argumentsArray, new CXUnsavedFile[] { new CXUnsavedFile()
                                                                                                                                        {
                                                                                                                                            Contents = rootFileContent,
                                                                                                                                            Filename = rootFileName,
                                                                                                                                            Length   = (uint)Encoding.UTF8.GetByteCount(rootFileContent)
                                                                                                                                        } }, translationFlags, out translationUnit);
                    }
                    bool skipProcessing = false;

                    if (translationUnitError != CXErrorCode.CXError_Success)
                    {
                        compilation.Diagnostics.Error($"Parsing failed due to '{translationUnitError}'", new CppSourceLocation(rootFileName, 0, 1, 1));
                        skipProcessing = true;
                    }
                    else if (translationUnit.NumDiagnostics != 0)
                    {
                        for (uint i = 0; i < translationUnit.NumDiagnostics; ++i)
                        {
                            using (var diagnostic = translationUnit.GetDiagnostic(i))
                            {
                                switch (diagnostic.Severity)
                                {
                                case CXDiagnosticSeverity.CXDiagnostic_Ignored:
                                case CXDiagnosticSeverity.CXDiagnostic_Note:
                                    compilation.Diagnostics.Info(diagnostic.ToString(), CppModelBuilder.GetSourceLocation(diagnostic.Location));
                                    break;

                                case CXDiagnosticSeverity.CXDiagnostic_Warning:
                                    compilation.Diagnostics.Warning(diagnostic.ToString(), CppModelBuilder.GetSourceLocation(diagnostic.Location));
                                    break;

                                case CXDiagnosticSeverity.CXDiagnostic_Error:
                                case CXDiagnosticSeverity.CXDiagnostic_Fatal:
                                    compilation.Diagnostics.Error(diagnostic.ToString(), CppModelBuilder.GetSourceLocation(diagnostic.Location));
                                    skipProcessing = true;
                                    break;
                                }
                            }
                        }
                    }

                    if (skipProcessing)
                    {
                        compilation.Diagnostics.Warning($"Compilation aborted due to one or more errors listed above.", new CppSourceLocation(rootFileName, 0, 1, 1));
                    }
                    else
                    {
                        using (translationUnit)
                        {
                            translationUnit.Cursor.VisitChildren(builder.VisitTranslationUnit, clientData: default);
                        }
                    }
                }

                return(compilation);
            }
        }