Reduce references to Extract class

This commit is contained in:
Tamas Vajk
2024-06-12 11:12:57 +02:00
parent 11faf08ed0
commit af2a78ea4d
13 changed files with 87 additions and 89 deletions

View File

@@ -81,7 +81,7 @@ namespace Semmle.Extraction.CSharp.Standalone
var canonicalPathCache = CanonicalPathCache.Create(logger, 1000); var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var pathTransformer = new PathTransformer(canonicalPathCache); var pathTransformer = new PathTransformer(canonicalPathCache);
using var analyser = new StandaloneAnalyser(pm, logger, false, pathTransformer); using var analyser = new StandaloneAnalyser(pm, logger, pathTransformer, canonicalPathCache, false);
try try
{ {
AnalyseStandalone(analyser, extractionInput, options, pm, stopwatch); AnalyseStandalone(analyser, extractionInput, options, pm, stopwatch);

View File

@@ -27,7 +27,7 @@ namespace Semmle.Extraction.CSharp.Entities
var mapped = Symbol.GetMappedLineSpan(); var mapped = Symbol.GetMappedLineSpan();
if (mapped.HasMappedPath && mapped.IsValid) if (mapped.HasMappedPath && mapped.IsValid)
{ {
var path = TryAdjustRelativeMappedFilePath(mapped.Path, Position.Path, Context.Extractor.Logger); var path = Context.TryAdjustRelativeMappedFilePath(mapped.Path, Position.Path);
var mappedLoc = Create(Context, Location.Create(path, default, mapped.Span)); var mappedLoc = Create(Context, Location.Create(path, default, mapped.Span));
trapFile.locations_mapped(this, mappedLoc); trapFile.locations_mapped(this, mappedLoc);
@@ -64,25 +64,5 @@ namespace Semmle.Extraction.CSharp.Entities
public override NonGeneratedSourceLocation Create(Context cx, Location init) => new NonGeneratedSourceLocation(cx, init); public override NonGeneratedSourceLocation Create(Context cx, Location init) => new NonGeneratedSourceLocation(cx, init);
} }
public static string TryAdjustRelativeMappedFilePath(string mappedToPath, string mappedFromPath, ILogger logger)
{
if (!Path.IsPathRooted(mappedToPath))
{
try
{
var fullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(mappedFromPath)!, mappedToPath));
logger.LogDebug($"Found relative path in line mapping: '{mappedToPath}', interpreting it as '{fullPath}'");
mappedToPath = fullPath;
}
catch (Exception e)
{
logger.LogDebug($"Failed to compute absolute path for relative path in line mapping: '{mappedToPath}': {e}");
}
}
return mappedToPath;
}
} }
} }

View File

@@ -28,7 +28,7 @@ namespace Semmle.Extraction.CSharp.Entities
var path = Symbol.File.ValueText; var path = Symbol.File.ValueText;
if (!string.IsNullOrWhiteSpace(path)) if (!string.IsNullOrWhiteSpace(path))
{ {
path = NonGeneratedSourceLocation.TryAdjustRelativeMappedFilePath(path, Symbol.SyntaxTree.FilePath, Context.Extractor.Logger); path = Context.TryAdjustRelativeMappedFilePath(path, Symbol.SyntaxTree.FilePath);
var file = File.Create(Context, path); var file = File.Create(Context, path);
trapFile.directive_line_file(this, file); trapFile.directive_line_file(this, file);
} }

View File

@@ -12,7 +12,7 @@ namespace Semmle.Extraction.CSharp.Entities
protected override void PopulatePreprocessor(TextWriter trapFile) protected override void PopulatePreprocessor(TextWriter trapFile)
{ {
var path = NonGeneratedSourceLocation.TryAdjustRelativeMappedFilePath(Symbol.File.ValueText, Symbol.SyntaxTree.FilePath, Context.Extractor.Logger); var path = Context.TryAdjustRelativeMappedFilePath(Symbol.File.ValueText, Symbol.SyntaxTree.FilePath);
var file = File.Create(Context, path); var file = File.Create(Context, path);
trapFile.pragma_checksums(this, file, Symbol.Guid.ToString(), Symbol.Bytes.ToString()); trapFile.pragma_checksums(this, file, Symbol.Guid.ToString(), Symbol.Bytes.ToString());
} }

View File

@@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.CSharp;
using Semmle.Util; using Semmle.Util;
using Semmle.Util.Logging; using Semmle.Util.Logging;
using Semmle.Extraction.CSharp.Populators; using Semmle.Extraction.CSharp.Populators;
using System.Reflection;
namespace Semmle.Extraction.CSharp namespace Semmle.Extraction.CSharp
{ {
@@ -38,14 +39,23 @@ namespace Semmle.Extraction.CSharp
public PathTransformer PathTransformer { get; } public PathTransformer PathTransformer { get; }
protected Analyser(IProgressMonitor pm, ILogger logger, bool addAssemblyTrapPrefix, PathTransformer pathTransformer) public IPathCache PathCache { get; }
protected Analyser(
IProgressMonitor pm,
ILogger logger,
PathTransformer pathTransformer,
IPathCache pathCache,
bool addAssemblyTrapPrefix)
{ {
Logger = logger; Logger = logger;
PathTransformer = pathTransformer;
PathCache = pathCache;
this.addAssemblyTrapPrefix = addAssemblyTrapPrefix; this.addAssemblyTrapPrefix = addAssemblyTrapPrefix;
this.progressMonitor = pm;
Logger.Log(Severity.Info, "EXTRACTION STARTING at {0}", DateTime.Now); Logger.Log(Severity.Info, "EXTRACTION STARTING at {0}", DateTime.Now);
stopWatch.Start(); stopWatch.Start();
progressMonitor = pm;
PathTransformer = pathTransformer;
} }
/// <summary> /// <summary>
@@ -333,11 +343,26 @@ namespace Semmle.Extraction.CSharp
/// <summary> /// <summary>
/// Logs information about the extractor. /// Logs information about the extractor.
/// </summary> /// </summary>
public void LogExtractorInfo(string extractorVersion) public void LogExtractorInfo()
{ {
Logger.Log(Severity.Info, " Extractor: {0}", Environment.GetCommandLineArgs().First()); Logger.Log(Severity.Info, " Extractor: {0}", Environment.GetCommandLineArgs().First());
Logger.Log(Severity.Info, " Extractor version: {0}", extractorVersion); Logger.Log(Severity.Info, " Extractor version: {0}", Version);
Logger.Log(Severity.Info, " Current working directory: {0}", Directory.GetCurrentDirectory()); Logger.Log(Severity.Info, " Current working directory: {0}", Directory.GetCurrentDirectory());
} }
private static string Version
{
get
{
// the attribute for the git information are always attached to the entry assembly by our build system
var assembly = Assembly.GetEntryAssembly();
var versionString = assembly?.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
if (versionString == null)
{
return "unknown (not built from internal bazel workspace)";
}
return versionString.InformationalVersion;
}
}
} }
} }

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Semmle.Extraction.Entities; using Semmle.Extraction.Entities;
@@ -178,5 +179,25 @@ namespace Semmle.Extraction.CSharp
extractedGenerics.Add(entity.Label); extractedGenerics.Add(entity.Label);
return true; return true;
} }
public string TryAdjustRelativeMappedFilePath(string mappedToPath, string mappedFromPath)
{
if (!Path.IsPathRooted(mappedToPath))
{
try
{
var fullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(mappedFromPath)!, mappedToPath));
Extractor.Logger.LogDebug($"Found relative path in line mapping: '{mappedToPath}', interpreting it as '{fullPath}'");
mappedToPath = fullPath;
}
catch (Exception e)
{
Extractor.Logger.LogDebug($"Failed to compute absolute path for relative path in line mapping: '{mappedToPath}': {e}");
}
}
return mappedToPath;
}
} }
} }

View File

@@ -105,7 +105,7 @@ namespace Semmle.Extraction.CSharp
var canonicalPathCache = CanonicalPathCache.Create(logger, 1000); var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var pathTransformer = new PathTransformer(canonicalPathCache); var pathTransformer = new PathTransformer(canonicalPathCache);
using var analyser = new TracingAnalyser(new LogProgressMonitor(logger), logger, options.AssemblySensitiveTrap, pathTransformer); using var analyser = new TracingAnalyser(new LogProgressMonitor(logger), logger, pathTransformer, canonicalPathCache, options.AssemblySensitiveTrap);
try try
{ {
@@ -144,7 +144,7 @@ namespace Semmle.Extraction.CSharp
return ExitCode.Ok; return ExitCode.Ok;
} }
return AnalyseTracing(workingDirectory, compilerArgs, analyser, compilerArguments, options, canonicalPathCache, stopwatch); return AnalyseTracing(workingDirectory, compilerArgs, analyser, compilerArguments, options, stopwatch);
} }
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions] catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
{ {
@@ -226,7 +226,7 @@ namespace Semmle.Extraction.CSharp
/// The resolved references will be added (thread-safely) to the supplied /// The resolved references will be added (thread-safely) to the supplied
/// list <paramref name="ret"/>. /// list <paramref name="ret"/>.
/// </summary> /// </summary>
private static IEnumerable<Action> ResolveReferences(Microsoft.CodeAnalysis.CommandLineArguments args, Analyser analyser, CanonicalPathCache canonicalPathCache, BlockingCollection<MetadataReference> ret) private static IEnumerable<Action> ResolveReferences(Microsoft.CodeAnalysis.CommandLineArguments args, Analyser analyser, BlockingCollection<MetadataReference> ret)
{ {
var referencePaths = new Lazy<string[]>(() => FixedReferencePaths(args).ToArray()); var referencePaths = new Lazy<string[]>(() => FixedReferencePaths(args).ToArray());
return args.MetadataReferences.Select<CommandLineReference, Action>(clref => () => return args.MetadataReferences.Select<CommandLineReference, Action>(clref => () =>
@@ -235,7 +235,7 @@ namespace Semmle.Extraction.CSharp
{ {
if (File.Exists(clref.Reference)) if (File.Exists(clref.Reference))
{ {
var reference = MakeReference(clref, canonicalPathCache.GetCanonicalPath(clref.Reference)); var reference = MakeReference(clref, analyser.PathCache.GetCanonicalPath(clref.Reference));
ret.Add(reference); ret.Add(reference);
} }
else else
@@ -252,7 +252,7 @@ namespace Semmle.Extraction.CSharp
var composed = referencePaths.Value var composed = referencePaths.Value
.Select(path => Path.Combine(path, clref.Reference)) .Select(path => Path.Combine(path, clref.Reference))
.Where(path => File.Exists(path)) .Where(path => File.Exists(path))
.Select(path => canonicalPathCache.GetCanonicalPath(path)) .Select(path => analyser.PathCache.GetCanonicalPath(path))
.FirstOrDefault(); .FirstOrDefault();
if (composed is not null) if (composed is not null)
@@ -382,11 +382,10 @@ namespace Semmle.Extraction.CSharp
TracingAnalyser analyser, TracingAnalyser analyser,
CSharpCommandLineArguments compilerArguments, CSharpCommandLineArguments compilerArguments,
Options options, Options options,
CanonicalPathCache canonicalPathCache,
Stopwatch stopwatch) Stopwatch stopwatch)
{ {
return Analyse(stopwatch, analyser, options, return Analyse(stopwatch, analyser, options,
references => ResolveReferences(compilerArguments, analyser, canonicalPathCache, references), references => ResolveReferences(compilerArguments, analyser, references),
(analyser, syntaxTrees) => (analyser, syntaxTrees) =>
{ {
var paths = compilerArguments.SourceFiles var paths = compilerArguments.SourceFiles
@@ -399,7 +398,7 @@ namespace Semmle.Extraction.CSharp
} }
return ReadSyntaxTrees( return ReadSyntaxTrees(
paths.Select(canonicalPathCache.GetCanonicalPath), paths.Select(analyser.PathCache.GetCanonicalPath),
analyser, analyser,
compilerArguments.ParseOptions, compilerArguments.ParseOptions,
compilerArguments.Encoding, compilerArguments.Encoding,

View File

@@ -2,14 +2,15 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Semmle.Util;
using Semmle.Util.Logging; using Semmle.Util.Logging;
namespace Semmle.Extraction.CSharp namespace Semmle.Extraction.CSharp
{ {
public class StandaloneAnalyser : Analyser public class StandaloneAnalyser : Analyser
{ {
public StandaloneAnalyser(IProgressMonitor pm, ILogger logger, bool addAssemblyTrapPrefix, PathTransformer pathTransformer) public StandaloneAnalyser(IProgressMonitor pm, ILogger logger, PathTransformer pathTransformer, IPathCache pathCache, bool addAssemblyTrapPrefix)
: base(pm, logger, addAssemblyTrapPrefix, pathTransformer) : base(pm, logger, pathTransformer, pathCache, addAssemblyTrapPrefix)
{ {
} }
@@ -18,7 +19,7 @@ namespace Semmle.Extraction.CSharp
compilation = compilationIn; compilation = compilationIn;
extractor = new Extraction.Extractor(Directory.GetCurrentDirectory(), [], outputPath, compilationInfos, Logger, PathTransformer, ExtractorMode.Standalone, options.QlTest); extractor = new Extraction.Extractor(Directory.GetCurrentDirectory(), [], outputPath, compilationInfos, Logger, PathTransformer, ExtractorMode.Standalone, options.QlTest);
this.options = options; this.options = options;
LogExtractorInfo(Extraction.Extractor.Version); LogExtractorInfo();
SetReferencePaths(); SetReferencePaths();
} }

View File

@@ -13,8 +13,8 @@ namespace Semmle.Extraction.CSharp
{ {
private bool init; private bool init;
public TracingAnalyser(IProgressMonitor pm, ILogger logger, bool addAssemblyTrapPrefix, PathTransformer pathTransformer) public TracingAnalyser(IProgressMonitor pm, ILogger logger, PathTransformer pathTransformer, IPathCache pathCache, bool addAssemblyTrapPrefix)
: base(pm, logger, addAssemblyTrapPrefix, pathTransformer) : base(pm, logger, pathTransformer, pathCache, addAssemblyTrapPrefix)
{ {
} }
@@ -25,7 +25,8 @@ namespace Semmle.Extraction.CSharp
/// <returns>A Boolean indicating whether to proceed with extraction.</returns> /// <returns>A Boolean indicating whether to proceed with extraction.</returns>
public bool BeginInitialize(IEnumerable<string> roslynArgs) public bool BeginInitialize(IEnumerable<string> roslynArgs)
{ {
return init = LogRoslynArgs(roslynArgs, Extraction.Extractor.Version); LogExtractorInfo();
return init = LogRoslynArgs(roslynArgs);
} }
/// <summary> /// <summary>
@@ -47,11 +48,11 @@ namespace Semmle.Extraction.CSharp
this.options = options; this.options = options;
this.compilation = compilation; this.compilation = compilation;
this.extractor = new Extraction.Extractor(cwd, args, GetOutputName(compilation, commandLineArguments), [], Logger, PathTransformer, ExtractorMode.None, options.QlTest); this.extractor = new Extraction.Extractor(cwd, args, GetOutputName(compilation, commandLineArguments), [], Logger, PathTransformer, ExtractorMode.None, options.QlTest);
LogDiagnostics(); var errorCount = LogDiagnostics(compilation);
SetReferencePaths(); SetReferencePaths();
CompilationErrors += FilteredDiagnostics.Count(); CompilationErrors += errorCount;
} }
/// <summary> /// <summary>
@@ -59,9 +60,8 @@ namespace Semmle.Extraction.CSharp
/// </summary> /// </summary>
/// <param name="roslynArgs">The arguments passed to Roslyn.</param> /// <param name="roslynArgs">The arguments passed to Roslyn.</param>
/// <returns>A Boolean indicating whether the same arguments have been logged previously.</returns> /// <returns>A Boolean indicating whether the same arguments have been logged previously.</returns>
private bool LogRoslynArgs(IEnumerable<string> roslynArgs, string extractorVersion) private bool LogRoslynArgs(IEnumerable<string> roslynArgs)
{ {
LogExtractorInfo(extractorVersion);
Logger.Log(Severity.Info, $" Arguments to Roslyn: {string.Join(' ', roslynArgs)}"); Logger.Log(Severity.Info, $" Arguments to Roslyn: {string.Join(' ', roslynArgs)}");
var tempFile = Extractor.GetCSharpArgsLogPath(Path.GetRandomFileName()); var tempFile = Extractor.GetCSharpArgsLogPath(Path.GetRandomFileName());
@@ -137,27 +137,27 @@ namespace Semmle.Extraction.CSharp
return Path.Combine(commandLineArguments.OutputDirectory, commandLineArguments.OutputFileName); return Path.Combine(commandLineArguments.OutputDirectory, commandLineArguments.OutputFileName);
} }
#nullable disable warnings private int LogDiagnostics(CSharpCompilation compilation)
/// <summary>
/// Logs detailed information about this invocation,
/// in the event that errors were detected.
/// </summary>
/// <returns>A Boolean indicating whether to proceed with extraction.</returns>
private void LogDiagnostics()
{ {
foreach (var error in FilteredDiagnostics) var filteredDiagnostics = compilation
.GetDiagnostics()
.Where(e => e.Severity >= DiagnosticSeverity.Error && !errorsToIgnore.Contains(e.Id))
.ToList();
foreach (var error in filteredDiagnostics)
{ {
Logger.Log(Severity.Error, " Compilation error: {0}", error); Logger.Log(Severity.Error, " Compilation error: {0}", error);
} }
if (FilteredDiagnostics.Any()) if (filteredDiagnostics.Count != 0)
{ {
foreach (var reference in compilation.References) foreach (var reference in compilation.References)
{ {
Logger.Log(Severity.Info, " Resolved reference {0}", reference.Display); Logger.Log(Severity.Info, " Resolved reference {0}", reference.Display);
} }
} }
return filteredDiagnostics.Count;
} }
private static readonly HashSet<string> errorsToIgnore = new HashSet<string> private static readonly HashSet<string> errorsToIgnore = new HashSet<string>
@@ -166,17 +166,5 @@ namespace Semmle.Extraction.CSharp
"CS1589", // XML referencing not supported "CS1589", // XML referencing not supported
"CS1569" // Error writing XML documentation "CS1569" // Error writing XML documentation
}; };
private IEnumerable<Diagnostic> FilteredDiagnostics
{
get
{
return extractor is null || extractor.Mode.HasFlag(ExtractorMode.Standalone) || compilation is null ? Enumerable.Empty<Diagnostic>() :
compilation.
GetDiagnostics().
Where(e => e.Severity >= DiagnosticSeverity.Error && !errorsToIgnore.Contains(e.Id));
}
}
#nullable restore warnings
} }
} }

View File

@@ -51,7 +51,7 @@ namespace Semmle.Extraction
try try
{ {
writingLabel = true; writingLabel = true;
entity.DefineLabel(TrapWriter.Writer, Extractor); entity.DefineLabel(TrapWriter.Writer);
} }
finally finally
{ {

View File

@@ -28,7 +28,7 @@ namespace Semmle.Extraction
public abstract TrapStackBehaviour TrapStackBehaviour { get; } public abstract TrapStackBehaviour TrapStackBehaviour { get; }
public void DefineLabel(TextWriter trapFile, Extractor extractor) public void DefineLabel(TextWriter trapFile)
{ {
trapFile.WriteLabel(this); trapFile.WriteLabel(this);
trapFile.Write("="); trapFile.Write("=");
@@ -40,7 +40,7 @@ namespace Semmle.Extraction
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions] catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
{ {
trapFile.WriteLine("\""); trapFile.WriteLine("\"");
extractor.Message(new Message($"Unhandled exception generating id: {ex.Message}", ToString() ?? "", null, ex.StackTrace)); Context.Extractor.Message(new Message($"Unhandled exception generating id: {ex.Message}", ToString() ?? "", null, ex.StackTrace));
} }
trapFile.WriteLine(); trapFile.WriteLine();
} }

View File

@@ -48,6 +48,6 @@ namespace Semmle.Extraction
/// </summary> /// </summary>
TrapStackBehaviour TrapStackBehaviour { get; } TrapStackBehaviour TrapStackBehaviour { get; }
void DefineLabel(TextWriter trapFile, Extractor extractor); void DefineLabel(TextWriter trapFile);
} }
} }

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using Semmle.Util.Logging; using Semmle.Util.Logging;
using CompilationInfo = (string key, string value); using CompilationInfo = (string key, string value);
@@ -110,21 +109,6 @@ namespace Semmle.Extraction
public ILogger Logger { get; private set; } public ILogger Logger { get; private set; }
public static string Version
{
get
{
// the attribute for the git information are always attached to the entry assembly by our build system
var assembly = Assembly.GetEntryAssembly();
var versionString = assembly?.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
if (versionString == null)
{
return "unknown (not built from internal bazel workspace)";
}
return versionString.InformationalVersion;
}
}
public PathTransformer PathTransformer { get; } public PathTransformer PathTransformer { get; }
} }
} }