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);
}
}
}