using Buildalyzer; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis.VisualBasic; namespace Codelyzer.Analysis.Build { public class FileBuildHandler : IDisposable { private Compilation _compilation; private Compilation _prePortCompilation; private List Errors { get; set; } private ILogger Logger; private string _projectPath; private Dictionary _fileInfo; private IEnumerable _frameworkMetaReferences; private IEnumerable _coreMetaReferences; public FileBuildHandler(ILogger logger, string projectPath, Dictionary fileInfo, List frameworkMetaReferences, List coreMetaReferences) { Logger = logger; _fileInfo = fileInfo; _frameworkMetaReferences = frameworkMetaReferences?.Select(m => MetadataReference.CreateFromFile(m)); _coreMetaReferences = coreMetaReferences?.Select(m => MetadataReference.CreateFromFile(m)); _projectPath = projectPath; Errors = new List(); } public FileBuildHandler(ILogger logger, string projectPath, Dictionary fileInfo, IEnumerable frameworkMetaReferences, IEnumerable coreMetaReferences) { Logger = logger; _fileInfo = fileInfo; _frameworkMetaReferences = frameworkMetaReferences; _coreMetaReferences = coreMetaReferences; _projectPath = projectPath; Errors = new List(); } public async Task> Build() { var results = new List(); var trees = new List(); await Task.Run(() => { if (_projectPath.EndsWith(".vbproj", StringComparison.OrdinalIgnoreCase)) { BuildVisualBasic(trees); } else { BuildCsharp(trees); } _fileInfo.Keys.ToList().ForEach(file => { var sourceFilePath = Path.GetRelativePath(_projectPath, file); var fileTree = trees.FirstOrDefault(t => t.FilePath == file); if (fileTree != null) { var fileResult = new SourceFileBuildResult { SyntaxTree = fileTree, PrePortSemanticModel = _prePortCompilation?.GetSemanticModel(fileTree), SemanticModel = _compilation?.GetSemanticModel(fileTree), SourceFileFullPath = file, SourceFilePath = sourceFilePath }; results.Add(fileResult); } else { Logger.LogError($"Cannot find a syntax tree for {file}"); } }); }); return results; } private void BuildCsharp(List trees) { foreach (var file in _fileInfo) { var fileContent = file.Value; var syntaxTree = CSharpSyntaxTree.ParseText(fileContent, path: file.Key); trees.Add(syntaxTree); } if (trees.Count != 0) { var projectName = Path.GetFileNameWithoutExtension(_projectPath); if (_frameworkMetaReferences?.Any() == true) { _prePortCompilation = CSharpCompilation.Create(projectName, trees, _frameworkMetaReferences); } if (_coreMetaReferences?.Any() == true) { _compilation = CSharpCompilation.Create(projectName, trees, _coreMetaReferences); } } } private void BuildVisualBasic(List trees) { foreach (var file in _fileInfo) { var fileContent = file.Value; var syntaxTree = VisualBasicSyntaxTree.ParseText(fileContent, path: file.Key); trees.Add(syntaxTree); } if (trees.Count != 0) { var projectName = Path.GetFileNameWithoutExtension(_projectPath); if (_frameworkMetaReferences?.Any() == true) { _prePortCompilation = VisualBasicCompilation.Create(projectName, trees, _frameworkMetaReferences); } if (_coreMetaReferences?.Any() == true) { _compilation = VisualBasicCompilation.Create(projectName, trees, _coreMetaReferences); } } } public void Dispose() { _compilation = null; Logger = null; } } }