Skip to content

Commit

Permalink
improve codeanalyzer (#249)
Browse files Browse the repository at this point in the history
* improve codeanalyzer
  • Loading branch information
DMarinhoCodacy authored Oct 22, 2024
1 parent 5f02ba0 commit f97c828
Showing 1 changed file with 37 additions and 53 deletions.
90 changes: 37 additions & 53 deletions src/Analyzer/CodeAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
Expand All @@ -24,11 +25,11 @@ public class CodeAnalyzer : Codacy.Engine.Seed.CodeAnalyzer, IDisposable
private readonly string sonarConfigurationPath;
private readonly ImmutableArray<DiagnosticAnalyzer> availableAnalyzers;
private readonly DiagnosticsRunner diagnosticsRunner;

private readonly string tmpSonarLintFolder;
private static List<string> blacklist = new List<string> { "S1144", "S2325", "S2077"};
private static HashSet<string> blacklist = new HashSet<string> { "S1144", "S2325", "S2077" };

public static bool IsInBlacklist(string id) {
public static bool IsInBlacklist(string id)
{
return blacklist.Contains(id);
}

Expand All @@ -38,19 +39,21 @@ public CodeAnalyzer() : base(csharpExtension)
availableAnalyzers = ImmutableArray.Create(
new RuleFinder()
.GetAnalyzerTypes()
.Select(type => (DiagnosticAnalyzer) Activator.CreateInstance(type))
.Select(type => (DiagnosticAnalyzer)Activator.CreateInstance(type))
.ToArray());

var additionalFiles = new List<AnalyzerAdditionalFile>();

if (!(PatternIds is null) && PatternIds.Any())
{
// create temporary directory
// create temporary directory only if needed
this.tmpSonarLintFolder = Path.Combine(Path.GetTempPath(), "sonarlint_" + Guid.NewGuid());
Directory.CreateDirectory(tmpSonarLintFolder);
var tmpSonarLintPath = Path.Combine(tmpSonarLintFolder, defaultSonarConfiguration);

var rules = new XElement("Rules");
var patterns = CurrentTool.Patterns.Where(pattern => !IsInBlacklist(pattern.PatternId)).ToArray();

foreach (var pattern in patterns)
{
var parameters = new XElement("Parameters");
Expand All @@ -69,20 +72,17 @@ public CodeAnalyzer() : base(csharpExtension)

new XDocument(new XElement("AnalysisInput", rules)).Save(tmpSonarLintPath);
additionalFiles.Add(new AnalyzerAdditionalFile(tmpSonarLintPath));
} else if (File.Exists(sonarConfigurationPath)) {
additionalFiles.Add(new AnalyzerAdditionalFile(sonarConfigurationPath));
}

// if we don't have patterns let's get them from the config file
if (PatternIds is null && File.Exists(sonarConfigurationPath))
else if (File.Exists(sonarConfigurationPath))
{
var xmlDoc = XDocument.Load(sonarConfigurationPath);
var analysisInput = xmlDoc.Element("AnalysisInput");
var rules = analysisInput.Element("Rules");
var configurationFile = XDocument.Load(sonarConfigurationPath).Element("AnalysisInput");
additionalFiles.Add(new AnalyzerAdditionalFile(sonarConfigurationPath));

// Load patterns from cached configuration file
var rules = configurationFile.Element("Rules");
if (rules != null)
{
PatternIds = rules.Elements("Rule").Select(e => e.Elements("Key").Single().Value)
.ToImmutableList();
PatternIds = rules.Elements("Rule").Select(e => e.Elements("Key").Single().Value).ToImmutableList();
}
}

Expand All @@ -95,17 +95,13 @@ public void Dispose()
GC.SuppressFinalize(this);
}

/// <summary>
/// Free temporary resources created on object construction.
/// </summary>
~CodeAnalyzer()
{
Dispose(false);
}

protected virtual void Dispose(bool disposing)
{
// delete created temporary directory
if (tmpSonarLintFolder != null)
{
Directory.Delete(tmpSonarLintFolder, true);
Expand All @@ -114,19 +110,12 @@ protected virtual void Dispose(bool disposing)

protected override async Task Analyze(CancellationToken cancellationToken)
{
foreach (var file in Config.Files) {
// skip all files that don't have the main language extension
// To allow Semgrep to run on C# configuration files
// We are analyzing `Directory.Packages.props` as if it was a C# file
// This is to avoid that.
// More info here: https://codacy.zendesk.com/agent/tickets/44462
if (!file.EndsWith(".cs"))
{
continue;
}
// Process files concurrently for better performance
var fileAnalysisTasks = Config.Files
.Where(file => file.EndsWith(".cs")) // only analyze C# files
.Select(file => Analyze(file, cancellationToken));

await Analyze(file, cancellationToken).ConfigureAwait(false);
}
await Task.WhenAll(fileAnalysisTasks);
}

public async Task Analyze(string file, CancellationToken cancellationToken)
Expand All @@ -136,28 +125,24 @@ public async Task Analyze(string file, CancellationToken cancellationToken)
var solution = CompilationHelper.GetSolutionFromFile(DefaultSourceFolder + file);
var compilation = await solution.Projects.First().GetCompilationAsync();

foreach (var diagnostic in await diagnosticsRunner.GetDiagnostics(compilation, cancellationToken))
// Parallelize diagnostics fetching
var diagnostics = await diagnosticsRunner.GetDiagnostics(compilation, cancellationToken);

Parallel.ForEach(diagnostics, diagnostic =>
{
var result = new CodacyResult
{
Filename = file,
PatternId = diagnostic.Id,
Message = diagnostic.GetMessage()
Message = diagnostic.GetMessage(),
Line = diagnostic.Location != Location.None ? diagnostic.Location.GetLineNumberToReport() : 1
};

if (diagnostic.Location != Location.None)
{
result.Line = diagnostic.Location.GetLineNumberToReport();
}
else
if (!IsInBlacklist(diagnostic.Id))
{
result.Line = 1;
}

if(!IsInBlacklist(diagnostic.Id)) {
Console.WriteLine(result);
}
}
});
}
catch (Exception e)
{
Expand All @@ -177,27 +162,26 @@ public ImmutableArray<DiagnosticAnalyzer> GetAnalyzers()
{
return availableAnalyzers;
}
var builder = ImmutableArray.CreateBuilder<DiagnosticAnalyzer>();

foreach (var analyzer in availableAnalyzers
.Where(analyzer => analyzer.SupportedDiagnostics.Any(diagnostic => PatternIds.Contains(diagnostic.Id))))
builder.Add(analyzer);
// Initialize only relevant analyzers
var relevantAnalyzers = availableAnalyzers
.Where(analyzer => analyzer.SupportedDiagnostics.Any(diagnostic => PatternIds.Contains(diagnostic.Id)))
.ToImmutableArray();

return builder.ToImmutable();
return relevantAnalyzers;
}

public static ImmutableArray<DiagnosticAnalyzer> GetUtilityAnalyzers()
{
var builder = ImmutableArray.CreateBuilder<DiagnosticAnalyzer>();
var utilityAnalyzerTypes = RuleFinder.GetUtilityAnalyzerTypes()
.Where(t => !t.IsAbstract)
.ToList();

foreach (var analyzer in utilityAnalyzerTypes
.Select(type => (DiagnosticAnalyzer) Activator.CreateInstance(type)))
builder.Add(analyzer);
var utilityAnalyzers = utilityAnalyzerTypes
.Select(type => (DiagnosticAnalyzer)Activator.CreateInstance(type))
.ToImmutableArray();

return builder.ToImmutable();
return utilityAnalyzers;
}
}
}

0 comments on commit f97c828

Please sign in to comment.