using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Codelyzer.Analysis; using Codelyzer.Analysis.Analyzer; using Codelyzer.Analysis.Build; using CTA.Rules.Config; using CTA.Rules.Models; namespace CTA.Rules.Update { /// /// Runs rule updates on a solution /// public class SolutionRewriter { private readonly List _projectRewriters; private readonly SolutionResult _solutionResult; private readonly IProjectRewriterFactory _projectRewriterFactory; /// /// Initializes a new instance of SolutionRewriter, analyzing the solution path using the provided config. /// WARNING: This constructor will rebuild and reanalyze the solution, which will have a performance impact. If you /// have an already analyzed solution, use another constructor /// /// Configuration for code analyzer to be used (AnalyzerConfiguration) /// Path to solution file /// Configuration for each project in solution to be built public SolutionRewriter(string solutionFilePath, List solutionConfiguration, IProjectRewriterFactory projectRewriterFactory = null, bool syntaxOnly = false) { DownloadResourceFiles(); _solutionResult = new SolutionResult(); _projectRewriterFactory = projectRewriterFactory ?? new DefaultProjectRewriterFactory(); AnalyzerConfiguration analyzerConfiguration = new AnalyzerConfiguration(LanguageOptions.CSharp) { MetaDataSettings = new MetaDataSettings() { Annotations = true, DeclarationNodes = true, MethodInvocations = true, ReferenceData = true, LoadBuildData = true, InterfaceDeclarations = true, MemberAccess = true, ElementAccess = true }, BuildSettings = new BuildSettings() { SyntaxOnly = syntaxOnly } }; _projectRewriters = new List(); //CodeAnalyzer analyzer = CodeAnalyzerFactory.GetAnalyzer(analyzerConfiguration, LogHelper.Logger); CodeAnalyzerByLanguage analyzer = new CodeAnalyzerByLanguage(analyzerConfiguration, LogHelper.Logger); var analyzerResults = analyzer.AnalyzeSolution(solutionFilePath).Result; InitializeProjectRewriters(analyzerResults, solutionConfiguration); } /// /// Initializes a new instance of SolutionRewriter with an already analyzed solution /// /// The solution analysis /// Configuration for each project in the solution public SolutionRewriter(List analyzerResults, List solutionConfiguration, IProjectRewriterFactory projectRewriterFactory = null) { DownloadResourceFiles(); _solutionResult = new SolutionResult(); _projectRewriterFactory = projectRewriterFactory ?? new DefaultProjectRewriterFactory(); _projectRewriters = new List(); InitializeProjectRewriters(analyzerResults, solutionConfiguration); } public SolutionRewriter(IDEProjectResult projectResult, List solutionConfiguration, IProjectRewriterFactory projectRewriterFactory = null) { DownloadResourceFiles(); _projectRewriterFactory = projectRewriterFactory ?? new DefaultProjectRewriterFactory(); var projectConfiguration = solutionConfiguration.FirstOrDefault(s => s.ProjectPath == projectResult.ProjectPath); if (projectConfiguration != null) { var projectRewriter = _projectRewriterFactory.GetInstance(projectResult, projectConfiguration); _projectRewriters = new List {projectRewriter}; } } /// /// Initializes the SolutionRewriter /// public SolutionResult AnalysisRun() { var options = new ParallelOptions() { MaxDegreeOfParallelism = Constants.ThreadCount }; Parallel.ForEach(_projectRewriters, options, projectRewriter => { _solutionResult.ProjectResults.Add(projectRewriter.Initialize()); }); return _solutionResult; } /// /// Run the SolutionRewriter using a previously created analysis /// public SolutionResult Run(Dictionary projectActions) { var options = new ParallelOptions { MaxDegreeOfParallelism = Constants.ThreadCount }; Parallel.ForEach(_projectRewriters, options, projectRewriter => { var actionsToRun = projectActions[projectRewriter.ProjectConfiguration.ProjectPath]; var projectResult = projectRewriter.Run(actionsToRun); _solutionResult.ProjectResults.Add(projectResult); }); return _solutionResult; } public List RunIncremental(RootNodes projectRules, List updatedFiles) { var ideFileActions = new BlockingCollection(); var options = new ParallelOptions { MaxDegreeOfParallelism = Constants.ThreadCount }; Parallel.ForEach(_projectRewriters, options, projectRewriter => { var result = projectRewriter.RunIncremental(updatedFiles, projectRules); result.ForEach(fileAction => ideFileActions.Add(fileAction)); }); return ideFileActions.ToList(); } /// /// Runs the solution rewriter after creating an analysis /// public SolutionResult Run() { var options = new ParallelOptions() { MaxDegreeOfParallelism = Constants.ThreadCount }; Parallel.ForEach(_projectRewriters, options, projectRewriter => { var projectResult = projectRewriter.Run(); var existingResult = _solutionResult.ProjectResults.FirstOrDefault(p => p.ProjectFile == projectResult.ProjectFile); if (existingResult == null) { _solutionResult.ProjectResults.Add(projectResult); } else { existingResult = projectResult; } }); return _solutionResult; } /// /// Initializes a rewriter for each project in the solution that has a configuration /// /// The list of analysis results for each project /// ProjectConfiguration for each project private void InitializeProjectRewriters(List analyzerResults, List solutionConfiguration) { foreach (var analyzerResult in analyzerResults) { var projectConfiguration = solutionConfiguration.Where(s => s.ProjectPath == analyzerResult.ProjectResult.ProjectFilePath).FirstOrDefault(); if (projectConfiguration != null) { var projectRewriter = _projectRewriterFactory.GetInstance(analyzerResult, projectConfiguration); _projectRewriters.Add(projectRewriter); } } } private void DownloadResourceFiles() { Utils.DownloadFilesToFolder(Constants.S3TemplatesBucketUrl, Constants.ResourcesExtractedPath, Constants.TemplateFiles); } } }