-
Notifications
You must be signed in to change notification settings - Fork 114
Remove -b flag for C# parser #846
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/csharp_plugin
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,9 @@ | |
|
|
||
| #include <memory> | ||
|
|
||
| #include <boost/property_tree/ptree.hpp> | ||
| #include <boost/property_tree/json_parser.hpp> | ||
|
|
||
| namespace cc | ||
| { | ||
| namespace parser | ||
|
|
@@ -27,11 +30,7 @@ CsharpParser::CsharpParser(ParserContext& ctx_): AbstractParser(ctx_) | |
| { | ||
| _threadNum = _ctx.options["jobs"].as<int>(); | ||
| } | ||
| /* | ||
| bool CsharpParser::acceptProjectBuildPath(const std::vector<std::string>& path_) | ||
| { | ||
| return path_.size() >= 2 && fs::is_directory(path_[0]) && fs::is_directory(path_[1]); | ||
| }*/ | ||
|
|
||
| bool CsharpParser::acceptProjectBuildPath(const std::string& buildPath_) | ||
| { | ||
| return fs::is_directory(buildPath_); | ||
|
|
@@ -42,26 +41,24 @@ bool CsharpParser::parse() | |
| bool success = true; | ||
|
|
||
| std::vector<std::string> paths = _ctx.options["input"].as<std::vector<std::string>>(); | ||
| std::string buildPath = _ctx.options["build-dir"].as<std::string>(); | ||
|
|
||
| if (acceptProjectBuildPath(buildPath)) | ||
| if (!paths.empty()) | ||
| { | ||
| LOG(debug) << "C# parser parse path: " << paths[0]; | ||
| LOG(debug) << "Parsed csharp project build path: " << buildPath; | ||
| success = success && parseProjectBuildPath(paths, buildPath); | ||
| LOG(debug) << "C# parser parse path: " << paths.size(); | ||
| success = success && parseProjectBuildPath(paths); | ||
| } | ||
| else | ||
| { | ||
| LOG(error) << "Build path must be a directory!"; | ||
| LOG(error) << "No input directories provided for C# parser!"; | ||
| success = false; | ||
| } | ||
|
|
||
| return success; | ||
| } | ||
|
|
||
| bool CsharpParser::parseProjectBuildPath( | ||
| const std::vector<std::string>& paths_, | ||
| const std::string& buildPath_) | ||
| const std::vector<std::string>& paths_ //, | ||
| ) | ||
| { | ||
| namespace ch = std::chrono; | ||
| std::future<std::string> log; | ||
|
|
@@ -80,8 +77,6 @@ bool CsharpParser::parseProjectBuildPath( | |
| command.append("'"); | ||
| command.append(_ctx.options["database"].as<std::string>()); | ||
| command.append("' '"); | ||
| command.append(buildPath_); | ||
| command.append("' '"); | ||
| command.append(csharp_path.string()); | ||
| command.append("' "); | ||
| command.append(std::to_string(_ctx.options["jobs"].as<int>())); | ||
|
|
@@ -108,22 +103,38 @@ bool CsharpParser::parseProjectBuildPath( | |
|
|
||
| std::string line; | ||
| std::stringstream log_str(log.get()); | ||
| //LOG(warning) << log_str.str(); | ||
| int countFull = 0, countPart = 0; | ||
|
|
||
| while(std::getline(log_str, line, '\n')) | ||
| { | ||
| if (line[0] == '+' || line[0] == '-') | ||
| // Skip empty lines or non-JSON lines (like debug info "ParallelRun ...") | ||
| if (line.empty() || line[0] != '{') continue; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really get this, in a valid JSON file / content, not every line starts with a |
||
|
|
||
| try | ||
| { | ||
| addSource(line.substr(1), line[0] == '-'); | ||
| if (line[0] == '+') | ||
| { | ||
| countFull++; | ||
| } | ||
| else | ||
| { | ||
| countPart++; | ||
| } | ||
| std::stringstream jsonStream(line); | ||
| boost::property_tree::ptree pt; | ||
| boost::property_tree::read_json(jsonStream, pt); | ||
|
|
||
| bool fullyParsed = pt.get<bool>("fullyParsed"); | ||
| std::string filepath = pt.get<std::string>("filePath"); | ||
| std::string targetDll = pt.get<std::string>("targetDll"); | ||
|
|
||
| // Check if it's an error based on 'fullyParsed' | ||
| bool isError = !fullyParsed; | ||
|
|
||
| addSource(filepath, targetDll, isError); | ||
|
|
||
| if (fullyParsed) { countFull++; } | ||
| else { countPart++; } | ||
| } | ||
| catch (const boost::property_tree::json_parser::json_parser_error& e) | ||
| { | ||
| LOG(warning) << "Failed to parse JSON output from C# parser: " << e.what() << " | Line: " << line; | ||
| } | ||
| catch (const boost::property_tree::ptree_error& e) | ||
| { | ||
| LOG(warning) << "Missing expected JSON field from C# parser: " << e.what() << " | Line: " << line; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -138,12 +149,12 @@ bool CsharpParser::parseProjectBuildPath( | |
| return result == 0; | ||
| } | ||
|
|
||
| void CsharpParser::addSource(const std::string& filepath_, bool error_) | ||
| void CsharpParser::addSource(const std::string& filepath_, const std::string& targetDll_, bool error_) | ||
| { | ||
| util::OdbTransaction transaction(_ctx.db); | ||
|
|
||
| model::BuildActionPtr buildAction(new model::BuildAction); | ||
| buildAction->command = " "; | ||
| buildAction->command = "dotnet build "; | ||
| buildAction->type = model::BuildAction::Compile; | ||
|
|
||
| model::BuildSource buildSource; | ||
|
|
@@ -176,10 +187,6 @@ extern "C" | |
| { | ||
| boost::program_options::options_description description("C# Plugin"); | ||
|
|
||
| description.add_options() | ||
| ("build-dir,b", po::value<std::string>()->default_value("Build directory"), | ||
| "The build directory of the parsed project."); | ||
|
|
||
| return description; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,14 +9,14 @@ | |
| using System.Collections.Generic; | ||
| using System.Threading.Tasks; | ||
| using CSharpParser.model; | ||
| using System.Xml.Linq; | ||
| using System.Text.Json; | ||
|
|
||
| namespace CSharpParser | ||
| { | ||
| class Program | ||
| { | ||
| //private readonly CsharpDbContext _context; | ||
| private static List<string> _rootDir; | ||
| private static string _buildDir = ""; | ||
| private static string _buildDirBase = ""; | ||
| private static string _connectionString = ""; | ||
|
|
||
|
|
@@ -28,11 +28,10 @@ static int Main(string[] args) | |
| try | ||
| { | ||
| _connectionString = args[0].Replace("'", ""); | ||
| _buildDir = args[1].Replace("'", ""); | ||
| _buildDirBase = args[2].Replace("'", ""); | ||
| threadNum = int.Parse(args[3]); | ||
| _buildDirBase = args[1].Replace("'", ""); //indexes | ||
| threadNum = int.Parse(args[2]); | ||
|
|
||
| for (int i = 4; i < args.Length; ++i) | ||
| for (int i = 3; i < args.Length; ++i) | ||
| { | ||
| _rootDir.Add(args[i].Replace("'", "")); | ||
| } | ||
|
|
@@ -42,44 +41,6 @@ static int Main(string[] args) | |
| WriteLine("Error in parsing command!"); | ||
| return 1; | ||
| } | ||
| /*if (args.Length < 3) | ||
| { | ||
| WriteLine("Missing command-line arguments in CSharpParser!"); | ||
| return 1; | ||
| } | ||
| else if (args.Length == 3) | ||
| { | ||
| _connectionString = args[0].Replace("'", ""); | ||
| _rootDir = args[1].Replace("'", ""); | ||
| _buildDir = args[2].Replace("'", ""); | ||
| } | ||
| else if (args.Length == 4) | ||
| { | ||
| _connectionString = args[0].Replace("'", ""); | ||
| _rootDir = args[1].Replace("'", ""); | ||
| _buildDir = args[2].Replace("'", ""); | ||
| bool success = int.TryParse(args[3], out threadNum); | ||
| if (!success){ | ||
| WriteLine("Invalid threadnumber argument! Multithreaded parsing disabled!"); | ||
| } | ||
| } | ||
| else if (args.Length == 5) | ||
| { | ||
| _connectionString = args[0].Replace("'", ""); | ||
| _rootDir = args[1].Replace("'", ""); | ||
| _buildDir = args[2].Replace("'", ""); | ||
| _buildDirBase = args[3].Replace("'", ""); | ||
| bool success = int.TryParse(args[4], out threadNum); | ||
| if (!success) | ||
| { | ||
| WriteLine("Invalid threadnumber argument! Multithreaded parsing disabled!"); | ||
| } | ||
| } | ||
| else if (args.Length > 5) | ||
| { | ||
| WriteLine("Too many command-line arguments in CSharpParser!"); | ||
| return 1; | ||
| }*/ | ||
|
|
||
| //Converting the connectionstring into entiy framwork style connectionstring | ||
| string csharpConnectionString = transformConnectionString(); | ||
|
|
@@ -91,21 +52,35 @@ static int Main(string[] args) | |
| CsharpDbContext _context = new CsharpDbContext(options); | ||
| _context.Database.Migrate(); | ||
|
|
||
|
|
||
| List<string> allFiles = new List<string>(); | ||
| // This dictionary will remember which file belongs to which DLL | ||
| Dictionary<string, string> fileToTargetDll = new Dictionary<string, string>(); | ||
|
|
||
| foreach (var p in _rootDir) | ||
| { | ||
| Console.WriteLine(p); | ||
| allFiles.AddRange(GetSourceFilesFromDir(p, ".cs")); | ||
| } | ||
| allFiles = allFiles.Distinct().ToList(); | ||
|
|
||
| foreach (var f in allFiles) | ||
| { | ||
| WriteLine(f); | ||
| } | ||
| IEnumerable<string> assemblies = GetSourceFilesFromDir(_buildDir, ".dll"); | ||
| IEnumerable<string> assemblies_base = assemblies; | ||
| if (args.Length == 5) | ||
| assemblies_base = GetSourceFilesFromDir(_buildDirBase, ".dll"); | ||
|
|
||
|
|
||
| IEnumerable<string> assemblies_base = GetSourceFilesFromDir(_buildDirBase, ".dll"); //loading basic dlls | ||
|
mcserep marked this conversation as resolved.
|
||
|
|
||
| List<string> assemblies = new List<string>(); | ||
| foreach (var p in _rootDir) | ||
| { | ||
| // We search for all .dll files in all input directories | ||
| assemblies.AddRange(GetSourceFilesFromDir(p, ".dll")); | ||
| } | ||
| // Let's keep only one of each DLL based on the file name! | ||
| assemblies = assemblies.GroupBy(x => System.IO.Path.GetFileName(x)) | ||
| .Select(g => g.First()) | ||
| .ToList(); | ||
|
|
||
| List<SyntaxTree> trees = new List<SyntaxTree>(); | ||
| foreach (string file in allFiles) | ||
|
|
@@ -129,14 +104,14 @@ static int Main(string[] args) | |
| compilation = compilation.AddReferences(MetadataReference.CreateFromFile(file)); | ||
| } | ||
|
|
||
| var runtask = ParalellRun(csharpConnectionString, threadNum, trees, compilation); | ||
| var runtask = ParalellRun(csharpConnectionString, threadNum, trees, compilation, fileToTargetDll); | ||
| int ret = runtask.Result; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| private static async Task<int> ParalellRun(string csharpConnectionString, int threadNum, | ||
| List<SyntaxTree> trees, CSharpCompilation compilation) | ||
| List<SyntaxTree> trees, CSharpCompilation compilation, Dictionary<string, string> fileToTargetDll) | ||
| { | ||
| var options = new DbContextOptionsBuilder<CsharpDbContext>() | ||
| .UseNpgsql(csharpConnectionString) | ||
|
|
@@ -156,7 +131,7 @@ private static async Task<int> ParalellRun(string csharpConnectionString, int th | |
| WriteLine(threadNum); | ||
| for (int i = 0; i < maxThread; i++) | ||
| { | ||
| ParsingTasks.Add(ParseTree(contextList[i],trees[i],compilation,i)); | ||
| ParsingTasks.Add(ParseTree(contextList[i],trees[i],compilation,i,fileToTargetDll)); | ||
| } | ||
|
|
||
| int nextTreeIndex = maxThread; | ||
|
|
@@ -169,7 +144,7 @@ private static async Task<int> ParalellRun(string csharpConnectionString, int th | |
| if (nextTreeIndex < trees.Count) | ||
| { | ||
| ParsingTasks.Add(ParseTree(contextList[nextContextIndex], | ||
| trees[nextTreeIndex],compilation,nextContextIndex)); | ||
| trees[nextTreeIndex],compilation,nextContextIndex, fileToTargetDll)); | ||
| ++nextTreeIndex; | ||
| } | ||
| } | ||
|
|
@@ -183,15 +158,28 @@ private static async Task<int> ParalellRun(string csharpConnectionString, int th | |
| } | ||
|
|
||
| private static async Task<int> ParseTree(CsharpDbContext context, | ||
| SyntaxTree tree, CSharpCompilation compilation, int index) | ||
| SyntaxTree tree, CSharpCompilation compilation, int index, | ||
| Dictionary<string, string> fileToTargetDll) | ||
| { | ||
| var ParsingTask = Task.Run(() => | ||
| { | ||
| WriteLine("ParallelRun " + tree.FilePath); | ||
| SemanticModel model = compilation.GetSemanticModel(tree); | ||
| var visitor = new AstVisitor(context, model, tree); | ||
| visitor.Visit(tree.GetCompilationUnitRoot()); | ||
| WriteLine((visitor.FullyParsed ? "+" : "-") + tree.FilePath); | ||
| visitor.Visit(tree.GetCompilationUnitRoot()); | ||
|
|
||
| // Find the DLL name and append a | to the filename. | ||
| string target = fileToTargetDll.ContainsKey(tree.FilePath) ? fileToTargetDll[tree.FilePath] : "Unknown.dll"; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As discussed on previous meeting, we shall not use a fake "Unknown.dll" filename. That could be a valid file. Use null or maybe empty string as extremal value. |
||
|
|
||
| var resultData = new | ||
| { | ||
| fullyParsed = visitor.FullyParsed, | ||
| filePath = tree.FilePath, | ||
| targetDll = target | ||
| }; | ||
|
|
||
| WriteLine(JsonSerializer.Serialize(resultData)); | ||
|
|
||
| return index; | ||
| }); | ||
| return await ParsingTask; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove commented out comma.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LakatosMark1 This is still a pending formatting issue.