From e1200bc5774c4c15aaaccb67565fa4a9b573fdf7 Mon Sep 17 00:00:00 2001
From: Joao Matos <joao@tritao.eu>
Date: Wed, 30 Aug 2017 17:27:42 +0100
Subject: [PATCH] [parser] Refactor the parser layer.

Removes some useless abstractions and unused code.

Signed-off-by: Joao Matos <joao@tritao.eu>
---
 src/CppParser/Parser.cpp              |  16 ----
 src/Generator.Tests/ASTTestFixture.cs |   1 -
 src/Generator/Driver.cs               |  53 ++++++-----
 src/Parser/Parser.cs                  |  46 +++------
 src/Parser/ParserOptions.cs           | 131 ++++++++++++++++----------
 src/Parser/Project.cs                 | 119 -----------------------
 6 files changed, 122 insertions(+), 244 deletions(-)
 delete mode 100644 src/Parser/Project.cs

diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp
index 3a2dd2c0..f8552c1d 100644
--- a/src/CppParser/Parser.cpp
+++ b/src/CppParser/Parser.cpp
@@ -4210,22 +4210,6 @@ ParserTargetInfo* Parser::GetTargetInfo()
 
     AST = &c->getASTContext();
 
-    // Initialize enough Clang codegen machinery so we can get at ABI details.
-    llvm::LLVMContext Ctx;
-    std::unique_ptr<llvm::Module> M(new llvm::Module("", Ctx));
-
-    M->setTargetTriple(AST->getTargetInfo().getTriple().getTriple());
-    M->setDataLayout(AST->getTargetInfo().getDataLayout());
-
-    std::unique_ptr<clang::CodeGen::CodeGenModule> CGM(
-        new clang::CodeGen::CodeGenModule(c->getASTContext(), c->getHeaderSearchOpts(),
-        c->getPreprocessorOpts(), c->getCodeGenOpts(), *M, c->getDiagnostics()));
-
-    std::unique_ptr<clang::CodeGen::CodeGenTypes> CGT(
-        new clang::CodeGen::CodeGenTypes(*CGM.get()));
-
-    codeGenTypes = CGT.get();
-
     auto parserTargetInfo = new ParserTargetInfo();
 
     auto& TI = AST->getTargetInfo();
diff --git a/src/Generator.Tests/ASTTestFixture.cs b/src/Generator.Tests/ASTTestFixture.cs
index 2c5c771d..5df84b3d 100644
--- a/src/Generator.Tests/ASTTestFixture.cs
+++ b/src/Generator.Tests/ASTTestFixture.cs
@@ -30,7 +30,6 @@ namespace CppSharp.Generator.Tests
             };
 
             Driver.Setup();
-            Driver.BuildParseOptions();
             if (!Driver.ParseCode())
                 throw new Exception("Error parsing the code");
 
diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs
index 0fe95a5a..92fd76ff 100644
--- a/src/Generator/Driver.cs
+++ b/src/Generator/Driver.cs
@@ -20,7 +20,6 @@ namespace CppSharp
     {
         public DriverOptions Options { get; private set; }
         public ParserOptions ParserOptions { get; set; }
-        public Project Project { get; private set; }
         public BindingContext Context { get; private set; }
         public Generator Generator { get; private set; }
 
@@ -29,7 +28,6 @@ namespace CppSharp
         public Driver(DriverOptions options)
         {
             Options = options;
-            Project = new Project();
             ParserOptions = new ParserOptions();
         }
 
@@ -74,9 +72,9 @@ namespace CppSharp
             Generator = CreateGeneratorFromKind(Options.GeneratorKind);
         }
 
-        void OnSourceFileParsed(IList<SourceFile> files, ParserResult result)
+        void OnSourceFileParsed(IEnumerable<string> files, ParserResult result)
         {
-            OnFileParsed(files.Select(f => f.Path), result);
+            OnFileParsed(files, result);
         }
 
         void OnFileParsed(string file, ParserResult result)
@@ -117,7 +115,7 @@ namespace CppSharp
             }
         }
 
-        public ParserOptions BuildParserOptions(SourceFile file = null)
+        public ParserOptions BuildParserOptions(string file = null)
         {
             var options = new ParserOptions
             {
@@ -177,7 +175,7 @@ namespace CppSharp
             }
 
             foreach (var module in Options.Modules.Where(
-                m => file == null || m.Headers.Contains(file.Path)))
+                m => file == null || m.Headers.Contains(file)))
             {
                 foreach (var include in module.IncludeDirs)
                     options.AddIncludeDirs(include);
@@ -197,30 +195,37 @@ namespace CppSharp
 
         public bool ParseCode()
         {
-            var parser = new ClangParser(new Parser.AST.ASTContext());
+            var astContext = new Parser.AST.ASTContext();
 
+            var parser = new ClangParser(astContext);
             parser.SourcesParsed += OnSourceFileParsed;
-            parser.ParseProject(Project, Options.UnityBuild);
 
-            foreach (var source in Project.Sources.Where(s => s.Options != null))
-                source.Options.Dispose();
+            var sourceFiles = Options.Modules.SelectMany(m => m.Headers);
 
-            Context.TargetInfo = parser.GetTargetInfo(ParserOptions);
-            Context.ASTContext = ClangParser.ConvertASTContext(parser.ASTContext);
+            if (Options.UnityBuild)
+            {
+                var parserOptions = BuildParserOptions();
+                var result = parser.ParseSourceFiles(sourceFiles, parserOptions);
+                result.Dispose();
+            }
+            else
+            {
+                var results = new List<ParserResult>();
 
-            return !hasParsingErrors;
-        }
+                foreach (var sourceFile in sourceFiles)
+                {
+                    var parserOptions = BuildParserOptions(sourceFile);
+                    results.Add(parser.ParseSourceFile(sourceFile, parserOptions));
+                }
 
-        public void BuildParseOptions()
-        {
-            foreach (var header in Options.Modules.SelectMany(m => m.Headers))
-            {
-                var source = Project.AddFile(header);
-                if (!Options.UnityBuild)
-                    source.Options = BuildParserOptions(source);
+                foreach (var result in results)
+                    result.Dispose();
             }
-            if (Options.UnityBuild)
-                Project.Sources[0].Options = BuildParserOptions();
+
+            Context.TargetInfo = parser.GetTargetInfo(ParserOptions);
+            Context.ASTContext = ClangParser.ConvertASTContext(astContext);
+
+            return !hasParsingErrors;
         }
 
         public void SortModulesByDependencies()
@@ -480,8 +485,6 @@ namespace CppSharp
             if (!options.Quiet)
                 Diagnostics.Message("Parsing code...");
 
-            driver.BuildParseOptions();
-
             if (!driver.ParseCode())
             {
                 Diagnostics.Error("CppSharp has encountered an error while parsing code.");
diff --git a/src/Parser/Parser.cs b/src/Parser/Parser.cs
index 4046788d..0a7fdbf0 100644
--- a/src/Parser/Parser.cs
+++ b/src/Parser/Parser.cs
@@ -18,7 +18,7 @@ namespace CppSharp
         /// <summary>
         /// Fired when source files are parsed.
         /// </summary>
-        public Action<IList<SourceFile>, ParserResult> SourcesParsed = delegate {};
+        public Action<IEnumerable<string>, ParserResult> SourcesParsed = delegate {};
 
         /// <summary>
         /// Fired when library files are parsed.
@@ -36,10 +36,8 @@ namespace CppSharp
         }
 
         /// <summary>
-        /// Get info about that target
+        /// Gets target information for a specific target triple.
         /// </summary>
-        /// <param name="options"></param>
-        /// <returns></returns>
         public ParserTargetInfo GetTargetInfo(ParserOptions options)
         {
             options.ASTContext = ASTContext;
@@ -48,47 +46,27 @@ namespace CppSharp
         }
 
         /// <summary>
-        /// Parses a C++ source file to a translation unit.
+        /// Parses a C++ source file as a translation unit.
         /// </summary>
-        private ParserResult ParseSourceFile(SourceFile file)
+        public ParserResult ParseSourceFile(string file, ParserOptions options)
         {
-            var options = file.Options;
-            options.ASTContext = ASTContext;
-            options.AddSourceFiles(file.Path);
-
-            var result = Parser.ClangParser.ParseHeader(options);
-            SourcesParsed(new[] { file }, result);
-
-            return result;
+            return ParseSourceFiles(new [] { file }, options);
         }
 
         /// <summary>
-        /// Parses C++ source files to a translation unit.
+        /// Parses a set of C++ source files as a single translation unit.
         /// </summary>
-        private void ParseSourceFiles(IList<SourceFile> files)
+        public ParserResult ParseSourceFiles(IEnumerable<string> files, ParserOptions options)
         {
-            var options = files[0].Options;
             options.ASTContext = ASTContext;
 
             foreach (var file in files)
-                options.AddSourceFiles(file.Path);
-            using (var result = Parser.ClangParser.ParseHeader(options))
-                SourcesParsed(files, result);
-        }
+                options.AddSourceFiles(file);
 
-        /// <summary>
-        /// Parses the project source files.
-        /// </summary>
-        public void ParseProject(Project project, bool unityBuild)
-        {
-            // TODO: Search for cached AST trees on disk
-            // TODO: Do multi-threaded parsing of source files
-
-            if (unityBuild)
-                ParseSourceFiles(project.Sources);
-            else
-                foreach (var parserResult in project.Sources.Select(s => ParseSourceFile(s)).ToList())
-                    parserResult.Dispose();
+            var result = Parser.ClangParser.ParseHeader(options);
+            SourcesParsed(files, result);
+
+            return result;
         }
 
         /// <summary>
diff --git a/src/Parser/ParserOptions.cs b/src/Parser/ParserOptions.cs
index 413c09a1..cd5d6fda 100644
--- a/src/Parser/ParserOptions.cs
+++ b/src/Parser/ParserOptions.cs
@@ -1,8 +1,45 @@
 using CppSharp.Parser.AST;
 using System.Reflection;
+using LanguageVersion = CppSharp.Parser.LanguageVersion;
 
 namespace CppSharp.Parser
 {
+    public enum LanguageVersion
+    {
+        /// <summary>
+        /// C programming language (year 1999).
+        /// </summary>
+        C99,
+        /// <summary>
+        /// C programming language (year 1999, GNU variant).
+        /// </summary>
+        C99_GNU,
+        /// <summary>
+        /// C++ programming language (year 1998).
+        /// </summary>
+        CPP98,
+        /// <summary>
+        /// C++ programming language (year 1998, GNU variant).
+        /// </summary>
+        CPP98_GNU,
+        /// <summary>
+        /// C++ programming language (year 2011).
+        /// </summary>
+        CPP11,
+        /// <summary>
+        /// C++ programming language (year 2011, GNU variant).
+        /// </summary>
+        CPP11_GNU,
+        /// <summary>
+        /// C++ programming language (year 2014).
+        /// </summary>
+        CPP14,
+        /// <summary>
+        /// C++ programming language (year 2014, GNU variant).
+        /// </summary>
+        CPP14_GNU
+    };
+
     public class ParserOptions : CppParserOptions
     {
         public ParserOptions()
@@ -12,12 +49,12 @@ namespace CppSharp.Parser
             CurrentDir = Assembly.GetExecutingAssembly().Location;
         }
 
-        public bool IsItaniumLikeAbi { get { return Abi != CppAbi.Microsoft; } }
-        public bool IsMicrosoftAbi { get { return Abi == CppAbi.Microsoft; } }
-        public bool EnableRtti { get; set; }
-        public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.GNUPlusPlus11;
+        public bool IsItaniumLikeAbi => Abi != CppAbi.Microsoft;
+        public bool IsMicrosoftAbi => Abi == CppAbi.Microsoft;
+
+        public bool EnableRTTI { get; set; }
+        public LanguageVersion? LanguageVersion { get; set; }
 
-        /// Sets up the parser options to work with the given Visual Studio toolchain.
         public void SetupMSVC()
         {
             VisualStudioVersion vsVersion = VisualStudioVersion.Latest;
@@ -43,9 +80,13 @@ namespace CppSharp.Parser
             #pragma warning restore 162
 
             }
+
             SetupMSVC(vsVersion);
         }
 
+        /// <summary>
+        /// Sets up the parser options to work with the given Visual Studio toolchain.
+        /// </summary>
         public void SetupMSVC(VisualStudioVersion vsVersion)
         {
             MicrosoftMode = true;
@@ -57,6 +98,10 @@ namespace CppSharp.Parser
             var includes = MSVCToolchain.GetSystemIncludes(vsVersion, out foundVsVersion);
             foreach (var include in includes)
                 AddSystemIncludeDirs(include);
+
+            if (!LanguageVersion.HasValue)
+                LanguageVersion = CppSharp.Parser.LanguageVersion.CPP14_GNU;
+
             var clVersion = MSVCToolchain.GetCLVersion(foundVsVersion);
             ToolSetToUse = clVersion.Major * 10000000 + clVersion.Minor * 100000;
 
@@ -85,15 +130,20 @@ namespace CppSharp.Parser
         public void Setup()
         {
             SetupArguments();
-            SetupIncludes();
+
+            if (!NoBuiltinIncludes)
+                SetupIncludes();
         }
 
         private void SetupArguments()
         {
+            if (!LanguageVersion.HasValue)
+                LanguageVersion = CppSharp.Parser.LanguageVersion.CPP14_GNU;
+
             switch (LanguageVersion)
             {
-                case LanguageVersion.C:
-                case LanguageVersion.GNUC:
+                case CppSharp.Parser.LanguageVersion.C99:
+                case CppSharp.Parser.LanguageVersion.C99_GNU:
                     AddArguments("-xc");
                     break;
                 default:
@@ -103,64 +153,47 @@ namespace CppSharp.Parser
 
             switch (LanguageVersion)
             {
-                case LanguageVersion.C:
+                case CppSharp.Parser.LanguageVersion.C99:
                     AddArguments("-std=c99");
                     break;
-                case LanguageVersion.GNUC:
+                case CppSharp.Parser.LanguageVersion.C99_GNU:
                     AddArguments("-std=gnu99");
                     break;
-                case LanguageVersion.CPlusPlus98:
+                case CppSharp.Parser.LanguageVersion.CPP98:
                     AddArguments("-std=c++98");
                     break;
-                case LanguageVersion.GNUPlusPlus98:
+                case CppSharp.Parser.LanguageVersion.CPP98_GNU:
                     AddArguments("-std=gnu++98");
                     break;
-                case LanguageVersion.CPlusPlus11:
-                    AddArguments(MicrosoftMode ? "-std=c++14" : "-std=c++11");
+                case CppSharp.Parser.LanguageVersion.CPP11:
+                    AddArguments("-std=c++11");
                     break;
-                default:
-                    AddArguments(MicrosoftMode ? "-std=gnu++14" : "-std=gnu++11");
+                case CppSharp.Parser.LanguageVersion.CPP11_GNU:
+                    AddArguments("-std=gnu++11");
+                    break;
+                case CppSharp.Parser.LanguageVersion.CPP14:
+                    AddArguments("-std=c++14");
+                    break;
+                case CppSharp.Parser.LanguageVersion.CPP14_GNU:
+                    AddArguments("-std=gnu++14");
                     break;
             }
 
-            if (!EnableRtti)
+            if (!EnableRTTI)
                 AddArguments("-fno-rtti");
         }
 
         private void SetupIncludes()
         {
-            if (Platform.IsMacOS)
-                SetupXcode();
-            else if (Platform.IsWindows && !NoBuiltinIncludes)
-                SetupMSVC();
+            switch(Platform.Host)
+            {
+                case TargetPlatform.Windows:
+                    SetupMSVC();
+                    break;
+                case TargetPlatform.MacOS:
+                    SetupXcode();
+                    break;
+            }
         }
     }
-
-    public enum LanguageVersion
-    {
-        /**
-        * The C programming language.
-        */
-        C,
-        /**
-        * The C programming language (GNU version).
-        */
-        GNUC,
-        /**
-        * The C++ programming language year 1998; supports deprecated constructs.
-        */
-        CPlusPlus98,
-        /**
-        * The C++ programming language year 1998; supports deprecated constructs (GNU version).
-        */
-        GNUPlusPlus98,
-        /**
-        * The C++ programming language year 2011.
-        */
-        CPlusPlus11,
-        /**
-        * The C++ programming language year 2011 (GNU version).
-        */
-        GNUPlusPlus11
-    };
 }
diff --git a/src/Parser/Project.cs b/src/Parser/Project.cs
deleted file mode 100644
index b679ed1a..00000000
--- a/src/Parser/Project.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-using System.Collections.Generic;
-using CppSharp.AST;
-using CppSharp.Parser;
-
-namespace CppSharp
-{
-    /// <summary>
-    /// Represents a reference to a source file.
-    /// </summary>
-    public class SourceFile
-    {
-        /// <summary>
-        /// Gets the file name.
-        /// </summary>
-        public string Name
-        {
-            get { return System.IO.Path.GetFileName(Path); }
-        }
-
-        /// <summary>
-        /// Gets the file path.
-        /// </summary>
-        public string Path { get; private set; }
-
-        /// <summary>
-        /// Gets/sets the parser options for the file.
-        /// </summary>
-        public ParserOptions Options { get; set; }
-
-        /// <summary>
-        /// Gets/sets the AST representation of the file.
-        /// </summary>
-        public TranslationUnit Unit { get; set; }
-
-        public SourceFile(string path)
-        {
-            Path = path;
-        }
-
-        public override string ToString()
-        {
-            return Path;
-        }
-    }
-
-    /// <summary>
-    /// Represents a C++ project with source and library files.
-    /// </summary>
-    public class Project
-    {
-        /// <summary>
-        /// List of per-project C/C++ preprocessor defines.
-        /// </summary>
-        public IList<string> Defines { get; private set; }
-
-        /// <summary>
-        /// List of per-project C/C++ include directories.
-        /// </summary>
-        public IList<string> IncludeDirs { get; private set; }
-
-        /// <summary>
-        /// List of per-project C/C++ system include directories.
-        /// </summary>
-        public IList<string> SystemIncludeDirs { get; private set; }
-
-        /// <summary>
-        /// List of source files in the project.
-        /// </summary>
-        public IList<SourceFile> Sources { get; private set; }
-
-        /// <summary>
-        /// Main AST context with translation units for the sources.
-        /// </summary>
-        public ASTContext ASTContext { get; private set; }
-
-        /// <summary>
-        /// Main symbols context with indexed library symbols.
-        /// </summary>
-        public SymbolContext SymbolsContext { get; private set; }
-        
-        public Project()
-        {
-            Defines = new List<string>();
-            IncludeDirs = new List<string>();
-            SystemIncludeDirs = new List<string>();
-
-            Sources = new List<SourceFile>();
-        }
-
-        /// <summary>
-        /// Adds a new source file to the project.
-        /// </summary>
-        public SourceFile AddFile(string path)
-        {
-            var sourceFile = new SourceFile(path);
-            Sources.Add(sourceFile);
-
-            return sourceFile;
-        }
-
-        /// <summary>
-        /// Adds a group of source files to the project.
-        /// </summary>
-        public void AddFiles(IEnumerable<string> paths)
-        {
-            foreach (var path in paths)
-                AddFile(path);
-        }
-
-        /// <summary>
-        /// Adds a new source file to the project.
-        /// </summary>
-        public void AddFolder(string path)
-        {
-            var sourceFile = new SourceFile(path);
-            Sources.Add(sourceFile);
-        }
-    }
-}