private async Task ValidateGeneratedBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions configOptions, string[] excludedNames, IReadOnlyDictionary <string, string> remappedNames, IReadOnlyDictionary <string, IReadOnlyList <string> > withAttributes, IReadOnlyDictionary <string, string> withCallConvs, IReadOnlyDictionary <string, string> withLibraryPaths, string[] withSetLastErrors, IReadOnlyDictionary <string, string> withTypes, IReadOnlyDictionary <string, IReadOnlyList <string> > withUsings, IEnumerable <Diagnostic> expectedDiagnostics, string libraryPath) { Assert.True(File.Exists(DefaultInputFileName)); using var outputStream = new MemoryStream(); using var unsavedFile = CXUnsavedFile.Create(DefaultInputFileName, inputContents); var unsavedFiles = new CXUnsavedFile[] { unsavedFile }; var config = new PInvokeGeneratorConfiguration(libraryPath, DefaultNamespaceName, Path.GetRandomFileName(), testOutputLocation: null, configOptions, excludedNames, headerFile: null, methodClassName: null, methodPrefixToStrip: null, remappedNames, traversalNames: null, withAttributes, withCallConvs, withLibraryPaths, withSetLastErrors, withTypes, withUsings); using (var pinvokeGenerator = new PInvokeGenerator(config, (path) => outputStream)) { var handle = CXTranslationUnit.Parse(pinvokeGenerator.IndexHandle, DefaultInputFileName, DefaultClangCommandLineArgs, unsavedFiles, DefaultTranslationUnitFlags); using var translationUnit = TranslationUnit.GetOrCreate(handle); pinvokeGenerator.GenerateBindings(translationUnit); if (expectedDiagnostics is null) { Assert.Empty(pinvokeGenerator.Diagnostics); } else { Assert.Equal(expectedDiagnostics, pinvokeGenerator.Diagnostics); } } outputStream.Position = 0; var actualOutputContents = await new StreamReader(outputStream).ReadToEndAsync(); Assert.Equal(expectedOutputContents, actualOutputContents); }
public void Run(string[] args, CodeBuilder result) { ParseCommandLineArgs(args, out var commandLineArgs, out var sourceContents); using (var unsavedFile = CXUnsavedFile.Create("Source", sourceContents)) using (var index = Index.Create(false, true)) { var unsavedFiles = new CXUnsavedFile[] { unsavedFile }; var handle = CXTranslationUnit.Parse( index.Handle, unsavedFile.FilenameString, commandLineArgs, unsavedFiles, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes // Include attributed types in CXType | CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes // Implicit attributes should be visited | CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies ); var translationUnit = TranslationUnit.GetOrCreate(handle); CheckTranslationUnitErrors(translationUnit, sourceContents); VisitTranslationUnit(translationUnit); } WriteNamespace(result); }
protected static TranslationUnit CreateTranslationUnit(string inputContents) { Assert.True(File.Exists(DefaultInputFileName)); using var unsavedFile = CXUnsavedFile.Create(DefaultInputFileName, inputContents); var unsavedFiles = new CXUnsavedFile[] { unsavedFile }; var index = CXIndex.Create(); var translationUnit = CXTranslationUnit.Parse(index, DefaultInputFileName, DefaultClangCommandLineArgs, unsavedFiles, DefaultTranslationUnitFlags); if (translationUnit.NumDiagnostics != 0) { var errorDiagnostics = new StringBuilder(); _ = errorDiagnostics.AppendLine($"The provided {nameof(CXTranslationUnit)} has the following diagnostics which prevent its use:"); var invalidTranslationUnitHandle = false; for (uint i = 0; i < translationUnit.NumDiagnostics; ++i) { using var diagnostic = translationUnit.GetDiagnostic(i); if (diagnostic.Severity is CXDiagnosticSeverity.CXDiagnostic_Error or CXDiagnosticSeverity.CXDiagnostic_Fatal) { invalidTranslationUnitHandle = true; _ = errorDiagnostics.Append(' ', 4); _ = errorDiagnostics.AppendLine(diagnostic.Format(CXDiagnosticDisplayOptions.CXDiagnostic_DisplayOption).ToString()); } } Assert.False(invalidTranslationUnitHandle, errorDiagnostics.ToString()); } return(TranslationUnit.GetOrCreate(translationUnit)); }
/// <summary> /// Build the Clang AST /// </summary> private TranslationUnit BuildClangAST(Configuration config, CXIndex index) { CXTranslationUnit tu = null; using (var section = CreateSection("Building Clang AST")) { // Assemble the arguments var clangArgs = new List <string>() { "-Wno-pragma-once-outside-header" }; switch (config.Clang.Language) { case LanguageEnum.C99: clangArgs.Add("-xc"); clangArgs.Add("-std=c99"); break; case LanguageEnum.Cpp11: clangArgs.Add("-xc++"); clangArgs.Add("-std=c++11"); break; case LanguageEnum.Cpp14: clangArgs.Add("-xc++"); clangArgs.Add("-std=c++14"); break; case LanguageEnum.Cpp17: clangArgs.Add("-xc++"); clangArgs.Add("-std=c++17"); break; default: throw new Exception($"unknown language {config.Clang.Language}"); } clangArgs.AddRange(GetWinSDKDIncludeArgs(config)); clangArgs.AddRange(GetCxxSTLIncludeArgs(config)); clangArgs.AddRange(config.Clang.Includes.Select(i => MakeIncludeArg(i))); clangArgs.AddRange(config.Clang.Defines.Select((m, v) => $"-D{m}=\"{v}\"")); clangArgs.AddRange(config.Clang.Arguments.Split(" ")); var tuFlags = CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies; // Create the TU source file var sourceFiles = new HashSet <string>(); config.Hook.Descriptions.Values.ToList().ForEach(hook => hook.Input.ForEach(source => sourceFiles.Add(source))); var tuFilename = Path.GetFileNameWithoutExtension(string.IsNullOrEmpty(config.Plugin.Name) ? Path.GetTempFileName() : config.Plugin.Name) + ".cpp"; Logger.Debug($"Clang TU filename: {tuFilename}"); var tuSource = "#include <" + string.Join(">\n#include <", sourceFiles) + ">"; Logger.Debug($"Clang TU source:\n {tuSource.Replace("\n", "\n ")}"); using (var tuSourceFile = CXUnsavedFile.Create(tuFilename, tuSource)) { // Invoke clang to get the TU Logger.Debug($"Clang args: {string.Join(" ", clangArgs)}"); var tuError = CXTranslationUnit.TryParse(index, tuSourceFile.FilenameString, clangArgs.ToArray(), new CXUnsavedFile[] { tuSourceFile }, tuFlags, out tu); if (tuError != CXErrorCode.CXError_Success) { throw new Exception($"clang error: failed to generate tanslation unit: {tuError}"); } } section.Done(); } if (tu == null) { return(null); } return(TranslationUnit.GetOrCreate(tu)); }