diff --git a/src/Basic.CompilerLog.UnitTests/Basic.CompilerLog.UnitTests.csproj b/src/Basic.CompilerLog.UnitTests/Basic.CompilerLog.UnitTests.csproj
index ba5c1fc..b2293c6 100644
--- a/src/Basic.CompilerLog.UnitTests/Basic.CompilerLog.UnitTests.csproj
+++ b/src/Basic.CompilerLog.UnitTests/Basic.CompilerLog.UnitTests.csproj
@@ -36,6 +36,9 @@
MetadataVersion1.console.complog
+
+ linux-console.complog
+
diff --git a/src/Basic.CompilerLog.UnitTests/CompilerLogReaderTests.cs b/src/Basic.CompilerLog.UnitTests/CompilerLogReaderTests.cs
index cdc63f8..e97737c 100644
--- a/src/Basic.CompilerLog.UnitTests/CompilerLogReaderTests.cs
+++ b/src/Basic.CompilerLog.UnitTests/CompilerLogReaderTests.cs
@@ -354,13 +354,15 @@ public void MetadataCompat(string resourceName)
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
using var stream = ResourceLoader.GetResourceStream(resourceName);
- using var reader = CompilerLogReader.Create(stream, leaveOpen: true, BasicAnalyzerHostOptions.None);
- foreach (var compilerCall in reader.ReadAllCompilerCalls())
- {
- var data = reader.ReadCompilationData(compilerCall);
- var result = data.EmitToMemory();
- Assert.True(result.Success);
- }
+ Assert.Throws(() => CompilerLogReader.Create(stream, leaveOpen: true, BasicAnalyzerHostOptions.None));
}
}
+
+ [Fact]
+ public void Disposed()
+ {
+ var reader = CompilerLogReader.Create(Fixture.ConsoleComplogPath.Value);
+ reader.Dispose();
+ Assert.Throws(() => reader.ReadCompilationData(0));
+ }
}
diff --git a/src/Basic.CompilerLog.UnitTests/ProgramTests.cs b/src/Basic.CompilerLog.UnitTests/ProgramTests.cs
index ceeb30e..edcd8f7 100644
--- a/src/Basic.CompilerLog.UnitTests/ProgramTests.cs
+++ b/src/Basic.CompilerLog.UnitTests/ProgramTests.cs
@@ -257,6 +257,22 @@ public void ResponseProjectFilter()
Assert.Contains("Program.cs", File.ReadAllLines(rsp));
}
+ [Fact]
+ public void ResponseOnCompilerLog()
+ {
+ var complogPath = Path.Combine(RootDirectory, "msbuild.complog");
+ Assert.Empty(CompilerLogUtil.ConvertBinaryLog(Fixture.SolutionBinaryLogPath, complogPath));
+ Assert.Equal(Constants.ExitSuccess, RunCompLog($"rsp {complogPath} -p console.csproj"));
+ }
+
+ [Fact]
+ public void ResponseOnInvalidFileType()
+ {
+ var (exitCode, output) = RunCompLogEx($"rsp data.txt -p console.csproj");
+ Assert.Equal(Constants.ExitFailure, exitCode);
+ Assert.Contains("Not a valid log", output);
+ }
+
[Fact]
public void ResponseAll()
{
@@ -283,6 +299,19 @@ public void ResponseBadOption()
Assert.Contains("complog rsp [OPTIONS]", output);
}
+ [Fact]
+ public void ResponseLinuxComplog()
+ {
+ var path = Path.Combine(RootDirectory, "console.complog");
+ File.WriteAllBytes(path, ResourceLoader.GetResourceBlob("linux-console.complog"));
+ var (exitCode, output) = RunCompLogEx($"rsp {path}");
+ Assert.Equal(Constants.ExitSuccess, exitCode);
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ Assert.Contains("generated on different operating system", output);
+ }
+ }
+
[Theory]
[InlineData("")]
[InlineData("--exclude-analyzers")]
diff --git a/src/Basic.CompilerLog.UnitTests/Resources/linux-console.complog b/src/Basic.CompilerLog.UnitTests/Resources/linux-console.complog
new file mode 100644
index 0000000..b0551b1
Binary files /dev/null and b/src/Basic.CompilerLog.UnitTests/Resources/linux-console.complog differ
diff --git a/src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs b/src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs
index 9f32e25..621c0b6 100644
--- a/src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs
+++ b/src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs
@@ -59,6 +59,20 @@ public async Task EmitToMemory()
}
}
+ [Fact]
+ public async Task CommandLineArguments()
+ {
+ await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper))
+ {
+ TestOutputHelper.WriteLine(complogPath);
+ using var reader = CompilerLogReader.Create(complogPath, options: BasicAnalyzerHostOptions.None);
+ foreach (var data in reader.ReadAllCompilerCalls())
+ {
+ Assert.NotEmpty(data.GetArguments());
+ }
+ }
+ }
+
[Theory]
[InlineData(true)]
[InlineData(false)]
diff --git a/src/Basic.CompilerLog.Util/CompilerLogReader.cs b/src/Basic.CompilerLog.Util/CompilerLogReader.cs
index fe73946..dc123b4 100644
--- a/src/Basic.CompilerLog.Util/CompilerLogReader.cs
+++ b/src/Basic.CompilerLog.Util/CompilerLogReader.cs
@@ -25,27 +25,34 @@
namespace Basic.CompilerLog.Util;
-public abstract class CompilerLogReader : IDisposable
+public sealed class CompilerLogReader : IDisposable
{
public static int LatestMetadataVersion => Metadata.LatestMetadataVersion;
+ ///
+ /// Stores the underlying archive this reader is using. Do not use directly. Instead
+ /// use which will throw if the reader is disposed
+ ///
+ private ZipArchive _zipArchiveCore;
+
private readonly Dictionary _refMap = new();
private readonly Dictionary _mvidToRefInfoMap = new();
private readonly Dictionary _analyzersMap = new();
private readonly bool _ownsCompilerLogState;
- private readonly Dictionary _compilationInfoMap = new();
+ private readonly Dictionary _compilationInfoMap = new();
public BasicAnalyzerHostOptions BasicAnalyzerHostOptions { get; }
internal CompilerLogState CompilerLogState { get; }
- internal ZipArchive ZipArchive { get; private set; }
internal Metadata Metadata { get; }
internal int Count => Metadata.Count;
public int MetadataVersion => Metadata.MetadataVersion;
public bool IsWindowsLog => Metadata.IsWindows == true;
+ public bool IsDisposed => _zipArchiveCore is null;
+ internal ZipArchive ZipArchive => !IsDisposed ? _zipArchiveCore : throw new ObjectDisposedException(nameof(CompilerLogReader));
- internal CompilerLogReader(ZipArchive zipArchive, Metadata metadata, BasicAnalyzerHostOptions basicAnalyzersOptions, CompilerLogState? state)
+ private CompilerLogReader(ZipArchive zipArchive, Metadata metadata, BasicAnalyzerHostOptions basicAnalyzersOptions, CompilerLogState? state)
{
- ZipArchive = zipArchive;
+ _zipArchiveCore = zipArchive;
CompilerLogState = state ?? new CompilerLogState();
_ownsCompilerLogState = state is null;
BasicAnalyzerHostOptions = basicAnalyzersOptions;
@@ -77,8 +84,8 @@ public static CompilerLogReader Create(
var zipArchive = new ZipArchive(stream, ZipArchiveMode.Read, leaveOpen);
var metadata = ReadMetadata();
return metadata.MetadataVersion switch {
- 1 => new CompilerLogReaderVersion1(zipArchive, metadata, options, state),
- 2 => new CompilerLogReaderVersion2(zipArchive, metadata, options, state),
+ 1 => throw new ArgumentException("Version 1 compiler logs are no longer supported"),
+ 2 => new CompilerLogReader(zipArchive, metadata, options, state),
_ => throw GetInvalidCompilerLogFileException(),
};
@@ -108,15 +115,73 @@ public static CompilerLogReader Create(
return Create(stream, leaveOpen: false, options, state);
}
- private protected abstract object ReadCompilationInfo(int index);
+ private CompilationInfoPack ReadCompilationInfo(int index)
+ {
+ using var stream = ZipArchive.OpenEntryOrThrow(GetCompilerEntryName(index));
+ return MessagePackSerializer.Deserialize(stream);
+ }
- private protected abstract CompilerCall ReadCompilerCallCore(int index, object rawInfo);
+ private CompilerCall ReadCompilerCallCore(int index, CompilationInfoPack pack)
+ {
+ return new CompilerCall(
+ pack.ProjectFilePath,
+ pack.CompilerCallKind,
+ pack.TargetFramework,
+ pack.IsCSharp,
+ new Lazy(() => GetContentPack(pack.CommandLineArgsHash)),
+ index);
+ }
- private protected abstract RawCompilationData ReadRawCompilationDataCore(int index, object rawInfo);
+ private RawCompilationData ReadRawCompilationDataCore(int index, CompilationInfoPack pack)
+ {
+ var dataPack = GetContentPack(pack.CompilationDataPackHash);
+
+ var references = dataPack
+ .References
+ .Select(x => new RawReferenceData(x.Mvid, x.Aliases, x.EmbedInteropTypes))
+ .ToList();
+ var analyzers = dataPack
+ .Analyzers
+ .Select(x => new RawAnalyzerData(x.Mvid, x.FilePath))
+ .ToList();
+ var contents = dataPack
+ .ContentList
+ .Select(x => new RawContent(x.Item2.FilePath, x.Item2.ContentHash, (RawContentKind)x.Item1))
+ .ToList();
+ var resources = dataPack
+ .Resources
+ .Select(x => new RawResourceData(x.ContentHash, CreateResourceDescription(this, x)))
+ .ToList();
+
+ return new RawCompilationData(
+ index,
+ compilationName: dataPack.ValueMap["compilationName"],
+ assemblyFileName: dataPack.ValueMap["assemblyFileName"]!,
+ xmlFilePath: dataPack.ValueMap["xmlFilePath"],
+ outputDirectory: dataPack.ValueMap["outputDirectory"],
+ dataPack.ChecksumAlgorithm,
+ references,
+ analyzers,
+ contents,
+ resources,
+ pack.IsCSharp,
+ dataPack.IncludesGeneratedText);
+
+ static ResourceDescription CreateResourceDescription(CompilerLogReader reader, ResourcePack pack)
+ {
+ var dataProvider = () =>
+ {
+ var bytes = reader.GetContentBytes(pack.ContentHash);
+ return new MemoryStream(bytes);
+ };
- private protected abstract (EmitOptions, ParseOptions, CompilationOptions) ReadCompilerOptionsCore(int index, object rawInfo);
+ return string.IsNullOrEmpty(pack.FileName)
+ ? new ResourceDescription(pack.Name, dataProvider, pack.IsPublic)
+ : new ResourceDescription(pack.Name, pack.FileName, dataProvider, pack.IsPublic);
+ }
+ }
- private object GetOrReadCompilationInfo(int index)
+ private CompilationInfoPack GetOrReadCompilationInfo(int index)
{
if (!_compilationInfoMap.TryGetValue(index, out var info))
{
@@ -154,8 +219,33 @@ public List ReadAllCompilerCalls(Func? predica
public (EmitOptions EmitOptions, ParseOptions ParseOptions, CompilationOptions CompilationOptions) ReadCompilerOptions(CompilerCall compilerCall)
{
var index = GetIndex(compilerCall);
- var info = GetOrReadCompilationInfo(index);
- return ReadCompilerOptionsCore(index, info);
+ var pack = GetOrReadCompilationInfo(index);
+ return ReadCompilerOptions(pack);
+ }
+
+ private (EmitOptions EmitOptions, ParseOptions ParseOptions, CompilationOptions CompilationOptions) ReadCompilerOptions(CompilationInfoPack pack)
+ {
+ var emitOptions = MessagePackUtil.CreateEmitOptions(GetContentPack(pack.EmitOptionsHash));
+ ParseOptions parseOptions;
+ CompilationOptions compilationOptions;
+ if (pack.IsCSharp)
+ {
+ var parseTuple = GetContentPack<(ParseOptionsPack, CSharpParseOptionsPack)>(pack.ParseOptionsHash);
+ parseOptions = MessagePackUtil.CreateCSharpParseOptions(parseTuple.Item1, parseTuple.Item2);
+
+ var optionsTuple = GetContentPack<(CompilationOptionsPack, CSharpCompilationOptionsPack)>(pack.CompilationOptionsHash);
+ compilationOptions = MessagePackUtil.CreateCSharpCompilationOptions(optionsTuple.Item1, optionsTuple.Item2);
+ }
+ else
+ {
+ var parseTuple = GetContentPack<(ParseOptionsPack, VisualBasicParseOptionsPack)>(pack.ParseOptionsHash);
+ parseOptions = MessagePackUtil.CreateVisualBasicParseOptions(parseTuple.Item1, parseTuple.Item2);
+
+ var optionsTuple = GetContentPack<(CompilationOptionsPack, VisualBasicCompilationOptionsPack, ParseOptionsPack, VisualBasicParseOptionsPack)>(pack.CompilationOptionsHash);
+ compilationOptions = MessagePackUtil.CreateVisualBasicCompilationOptions(optionsTuple.Item1, optionsTuple.Item2, optionsTuple.Item3, optionsTuple.Item4);
+ }
+
+ return (emitOptions, parseOptions, compilationOptions);
}
public CompilationData ReadCompilationData(int index) =>
@@ -163,11 +253,10 @@ public CompilationData ReadCompilationData(int index) =>
public CompilationData ReadCompilationData(CompilerCall compilerCall)
{
- var index = GetIndex(compilerCall);
- var info = GetOrReadCompilationInfo(index);
+ var pack = GetOrReadCompilationInfo(GetIndex(compilerCall));
var rawCompilationData = ReadRawCompilationData(compilerCall);
var referenceList = GetMetadataReferences(rawCompilationData.References);
- var (emitOptions, rawParseOptions, compilationOptions) = ReadCompilerOptionsCore(index, info);
+ var (emitOptions, rawParseOptions, compilationOptions) = ReadCompilerOptions(pack);
var hashAlgorithm = rawCompilationData.ChecksumAlgorithm;
var sourceTextList = new List<(SourceText SourceText, string Path)>();
@@ -606,13 +695,13 @@ internal void CopyAssemblyBytes(Guid mvid, Stream destination)
public void Dispose()
{
- if (ZipArchive is null)
+ if (IsDisposed)
{
return;
}
ZipArchive.Dispose();
- ZipArchive = null!;
+ _zipArchiveCore = null!;
if (_ownsCompilerLogState)
{
diff --git a/src/Basic.CompilerLog.Util/CompilerLogReaderVersion1.cs b/src/Basic.CompilerLog.Util/CompilerLogReaderVersion1.cs
deleted file mode 100644
index 3e9edc3..0000000
--- a/src/Basic.CompilerLog.Util/CompilerLogReaderVersion1.cs
+++ /dev/null
@@ -1,215 +0,0 @@
-using System.IO.Compression;
-using Basic.CompilerLog.Util;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Text;
-using CompilationInfo = System.Tuple;
-using static Basic.CompilerLog.Util.CommonUtil;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.VisualBasic;
-using Microsoft.CodeAnalysis.Emit;
-using System.Collections.Immutable;
-
-namespace Basic.CompilerLog.Util;
-
-internal sealed class CompilerLogReaderVersion1 : CompilerLogReader
-{
- internal CompilerLogReaderVersion1(ZipArchive zipArchive, Metadata metadata, BasicAnalyzerHostOptions basicAnalyzersOptions, CompilerLogState? state)
- :base(zipArchive, metadata, basicAnalyzersOptions, state)
- {
-
- }
-
- private protected override object ReadCompilationInfo(int index)
- {
- using var reader = Polyfill.NewStreamReader(ZipArchive.OpenEntryOrThrow(GetCompilerEntryName(index)), ContentEncoding, leaveOpen: false);
- var compilerCall = ReadCompilerCallCore(reader, index);
- var commandLineArguments = compilerCall.ParseArguments();
- return new CompilationInfo(compilerCall, commandLineArguments);
- }
-
- private protected override CompilerCall ReadCompilerCallCore(int index, object rawInfo)
- {
- var info = (CompilationInfo)rawInfo;
- return info.Item1;
- }
-
- private CompilerCall ReadCompilerCallCore(StreamReader reader, int index)
- {
- var projectFile = reader.ReadLineOrThrow();
- var isCSharp = reader.ReadLineOrThrow() == "C#";
- var targetFramework = reader.ReadLineOrThrow();
- if (string.IsNullOrEmpty(targetFramework))
- {
- targetFramework = null;
- }
-
- var kind = (CompilerCallKind)Enum.Parse(typeof(CompilerCallKind), reader.ReadLineOrThrow());
- var count = int.Parse(reader.ReadLineOrThrow());
- var arguments = new string[count];
- for (int i = 0; i < count; i++)
- {
- arguments[i] = reader.ReadLineOrThrow();
- }
-
- return new CompilerCall(projectFile, kind, targetFramework, isCSharp, new Lazy(() => arguments), index);
- }
-
- private protected override RawCompilationData ReadRawCompilationDataCore(int index, object rawInfo)
- {
- var info = (CompilationInfo)rawInfo;
- var args = info.Item2;
- using var reader = Polyfill.NewStreamReader(ZipArchive.OpenEntryOrThrow(GetCompilerEntryName(index)), ContentEncoding, leaveOpen: false);
- var compilerCall = ReadCompilerCallCore(reader, index);
-
- var references = new List();
- var analyzers = new List();
- var contents = new List();
- var resources = new List();
- var readGeneratedFiles = false;
-
- while (reader.ReadLine() is string line)
- {
- var colonIndex = line.IndexOf(':');
- switch (line.AsSpan().Slice(0, colonIndex))
- {
- case "m":
- ParseMetadataReference(line);
- break;
- case "a":
- ParseAnalyzer(line);
- break;
- case "source":
- ParseContent(line, RawContentKind.SourceText);
- break;
- case "generated":
- ParseContent(line, RawContentKind.GeneratedText);
- break;
- case "generatedResult":
- readGeneratedFiles = ParseBool();
- break;
- case "config":
- ParseContent(line, RawContentKind.AnalyzerConfig);
- break;
- case "text":
- ParseContent(line, RawContentKind.AdditionalText);
- break;
- case "embed":
- ParseContent(line, RawContentKind.Embed);
- break;
- case "embedline":
- ParseContent(line, RawContentKind.EmbedLine);
- break;
- case "link":
- ParseContent(line, RawContentKind.SourceLink);
- break;
- case "ruleset":
- ParseContent(line, RawContentKind.RuleSet);
- break;
- case "appconfig":
- ParseContent(line, RawContentKind.AppConfig);
- break;
- case "win32manifest":
- ParseContent(line, RawContentKind.Win32Manifest);
- break;
- case "win32resource":
- ParseContent(line, RawContentKind.Win32Resource);
- break;
- case "cryptokeyfile":
- ParseContent(line, RawContentKind.CryptoKeyFile);
- break;
- case "r":
- ParseResource(line);
- break;
- case "win32icon":
- ParseContent(line, RawContentKind.Win32Icon);
- break;
- default:
- throw new InvalidOperationException($"Unrecognized line: {line}");
- }
-
- bool ParseBool() =>
- colonIndex + 1 < line.Length &&
- line[colonIndex + 1] == '1';
- }
-
- var assemblyFileName = Path.GetFileNameWithoutExtension(compilerCall.ProjectFileName);
- var data = new RawCompilationData(
- index,
- args.CompilationName,
- assemblyFileName,
- args.DocumentationPath,
- args.OutputDirectory,
- args.ChecksumAlgorithm,
- references,
- analyzers,
- contents,
- resources,
- isCSharp: compilerCall.IsCSharp,
- readGeneratedFiles);
-
- return data;
-
- void ParseMetadataReference(string line)
- {
- var items = line.Split(':');
- if (items.Length == 5 &&
- Guid.TryParse(items[1], out var mvid) &&
- int.TryParse(items[2], out var kind))
- {
- var embedInteropTypes = items[3] == "1";
-
- var aliases = ImmutableArray.Empty;
- if (!string.IsNullOrEmpty(items[4]))
- {
- aliases = items[4].Split(',').ToImmutableArray();
- }
-
- references.Add(new RawReferenceData(
- mvid,
- aliases,
- embedInteropTypes));
- return;
- }
-
- throw new InvalidOperationException();
- }
-
- void ParseContent(string line, RawContentKind kind)
- {
- var items = line.Split(':', count: 3);
- contents.Add(new(items[2], items[1], kind));
- }
-
- void ParseResource(string line)
- {
- var items = line.Split(':', count: 5);
- var fileName = items[4];
- var isPublic = bool.Parse(items[3]);
- var contentHash = items[1];
- var dataProvider = () =>
- {
- var bytes = GetContentBytes(contentHash);
- return new MemoryStream(bytes);
- };
-
- var d = string.IsNullOrEmpty(fileName)
- ? new ResourceDescription(items[2], dataProvider, isPublic)
- : new ResourceDescription(items[2], fileName, dataProvider, isPublic);
- resources.Add(new(contentHash, d));
- }
-
- void ParseAnalyzer(string line)
- {
- var items = line.Split(':', count: 3);
- var mvid = Guid.Parse(items[1]);
- analyzers.Add(new RawAnalyzerData(mvid, items[2]));
- }
- }
-
- private protected override (EmitOptions, ParseOptions, CompilationOptions) ReadCompilerOptionsCore(int index, object rawInfo)
- {
- var info = (CompilationInfo)rawInfo;
- var args = info.Item2;
- return (args.EmitOptions, args.ParseOptions, args.CompilationOptions);
- }
-}
\ No newline at end of file
diff --git a/src/Basic.CompilerLog.Util/CompilerLogReaderVersion2.cs b/src/Basic.CompilerLog.Util/CompilerLogReaderVersion2.cs
deleted file mode 100644
index b5b09f5..0000000
--- a/src/Basic.CompilerLog.Util/CompilerLogReaderVersion2.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-using System.CodeDom.Compiler;
-using System.IO.Compression;
-using Basic.CompilerLog.Util;
-using Basic.CompilerLog.Util.Serialize;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Emit;
-using static Basic.CompilerLog.Util.CommonUtil;
-
-namespace Basic.CompilerLog.Util;
-
-internal sealed class CompilerLogReaderVersion2 : CompilerLogReader
-{
- internal CompilerLogReaderVersion2(ZipArchive zipArchive, Metadata metadata, BasicAnalyzerHostOptions basicAnalyzersOptions, CompilerLogState? state)
- :base(zipArchive, metadata, basicAnalyzersOptions, state)
- {
-
- }
-
- private protected override object ReadCompilationInfo(int index)
- {
- using var stream = ZipArchive.OpenEntryOrThrow(GetCompilerEntryName(index));
- return MessagePack.MessagePackSerializer.Deserialize(stream);
- }
-
- private protected override CompilerCall ReadCompilerCallCore(int index, object rawInfo)
- {
- var pack = (CompilationInfoPack)rawInfo;
- return new CompilerCall(
- pack.ProjectFilePath,
- pack.CompilerCallKind,
- pack.TargetFramework,
- pack.IsCSharp,
- new Lazy(() => GetContentPack(pack.CommandLineArgsHash)),
- index);
- }
-
- private protected override RawCompilationData ReadRawCompilationDataCore(int index, object rawInfo)
- {
- var pack = (CompilationInfoPack)rawInfo;
- var dataPack = GetContentPack(pack.CompilationDataPackHash);
-
- var references = dataPack
- .References
- .Select(x => new RawReferenceData(x.Mvid, x.Aliases, x.EmbedInteropTypes))
- .ToList();
- var analyzers = dataPack
- .Analyzers
- .Select(x => new RawAnalyzerData(x.Mvid, x.FilePath))
- .ToList();
- var contents = dataPack
- .ContentList
- .Select(x => new RawContent(x.Item2.FilePath, x.Item2.ContentHash, (RawContentKind)x.Item1))
- .ToList();
- var resources = dataPack
- .Resources
- .Select(x => new RawResourceData(x.ContentHash, CreateResourceDescription(this, x)))
- .ToList();
-
- return new RawCompilationData(
- index,
- compilationName: dataPack.ValueMap["compilationName"],
- assemblyFileName: dataPack.ValueMap["assemblyFileName"]!,
- xmlFilePath: dataPack.ValueMap["xmlFilePath"],
- outputDirectory: dataPack.ValueMap["outputDirectory"],
- dataPack.ChecksumAlgorithm,
- references,
- analyzers,
- contents,
- resources,
- pack.IsCSharp,
- dataPack.IncludesGeneratedText);
-
- static ResourceDescription CreateResourceDescription(CompilerLogReader reader, ResourcePack pack)
- {
- var dataProvider = () =>
- {
- var bytes = reader.GetContentBytes(pack.ContentHash);
- return new MemoryStream(bytes);
- };
-
- return string.IsNullOrEmpty(pack.FileName)
- ? new ResourceDescription(pack.Name, dataProvider, pack.IsPublic)
- : new ResourceDescription(pack.Name, pack.FileName, dataProvider, pack.IsPublic);
- }
- }
-
- private protected override (EmitOptions, ParseOptions, CompilationOptions) ReadCompilerOptionsCore(int index, object rawInfo)
- {
- var pack = (CompilationInfoPack)rawInfo;
- var emitOptions = MessagePackUtil.CreateEmitOptions(GetContentPack(pack.EmitOptionsHash));
- ParseOptions parseOptions;
- CompilationOptions compilationOptions;
- if (pack.IsCSharp)
- {
- var parseTuple = GetContentPack<(ParseOptionsPack, CSharpParseOptionsPack)>(pack.ParseOptionsHash);
- parseOptions = MessagePackUtil.CreateCSharpParseOptions(parseTuple.Item1, parseTuple.Item2);
-
- var optionsTuple = GetContentPack<(CompilationOptionsPack, CSharpCompilationOptionsPack)>(pack.CompilationOptionsHash);
- compilationOptions = MessagePackUtil.CreateCSharpCompilationOptions(optionsTuple.Item1, optionsTuple.Item2);
- }
- else
- {
- var parseTuple = GetContentPack<(ParseOptionsPack, VisualBasicParseOptionsPack)>(pack.ParseOptionsHash);
- parseOptions = MessagePackUtil.CreateVisualBasicParseOptions(parseTuple.Item1, parseTuple.Item2);
-
- var optionsTuple = GetContentPack<(CompilationOptionsPack, VisualBasicCompilationOptionsPack, ParseOptionsPack, VisualBasicParseOptionsPack)>(pack.CompilationOptionsHash);
- compilationOptions = MessagePackUtil.CreateVisualBasicCompilationOptions(optionsTuple.Item1, optionsTuple.Item2, optionsTuple.Item3, optionsTuple.Item4);
- }
-
- return (emitOptions, parseOptions, compilationOptions);
- }
-}
\ No newline at end of file
diff --git a/src/Basic.CompilerLog.Util/CompilerLogUtil.cs b/src/Basic.CompilerLog.Util/CompilerLogUtil.cs
index 5d7bed6..cceef92 100644
--- a/src/Basic.CompilerLog.Util/CompilerLogUtil.cs
+++ b/src/Basic.CompilerLog.Util/CompilerLogUtil.cs
@@ -109,18 +109,6 @@ public static ConvertBinaryLogResult TryConvertBinaryLog(Stream binaryLogStream,
return new ConvertBinaryLogResult(success, included, diagnostics);
}
- public static List ReadAllCompilerCalls(string compilerLogFilePath, Func? predicate = null)
- {
- using var compilerLogStream = new FileStream(compilerLogFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
- return ReadAllCompilerCalls(compilerLogStream, predicate);
- }
-
- public static List ReadAllCompilerCalls(Stream compilerLogStream, Func? predicate = null)
- {
- using var reader = CompilerLogReader.Create(compilerLogStream);
- return reader.ReadAllCompilerCalls(predicate);
- }
-
private static Exception CreateException(string message, IEnumerable diagnostics)
{
var builder = new StringBuilder();
diff --git a/src/Basic.CompilerLog/Program.cs b/src/Basic.CompilerLog/Program.cs
index 4ece268..07aa5a7 100644
--- a/src/Basic.CompilerLog/Program.cs
+++ b/src/Basic.CompilerLog/Program.cs
@@ -3,6 +3,7 @@
using Microsoft.CodeAnalysis;
using Mono.Options;
using StructuredLogViewer;
+using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using System.Text;
@@ -11,22 +12,13 @@
var (command, rest) = args.Length == 0
? ("help", Enumerable.Empty())
: (args[0], args.Skip(1));
-// a CancellationToken that is canceled when the user hits Ctrl+C.
-var cts = new CancellationTokenSource();
-
-Console.CancelKeyPress += (s, e) =>
-{
- WriteLine("Canceling...");
- cts.Cancel();
- e.Cancel = true;
-};
try
{
return command.ToLower() switch
{
"create" => RunCreate(rest),
- "replay" => RunReplay(rest, cts.Token),
+ "replay" => RunReplay(rest),
"export" => RunExport(rest),
"ref" => RunReferences(rest),
"rsp" => RunResponseFile(rest),
@@ -35,8 +27,8 @@
"help" => RunHelp(rest),
// Older option names
- "diagnostics" => RunReplay(rest, cts.Token),
- "emit" => RunReplay(rest, cts.Token),
+ "diagnostics" => RunReplay(rest),
+ "emit" => RunReplay(rest),
_ => RunBadCommand(command)
};
}
@@ -170,9 +162,8 @@ int RunPrint(IEnumerable args)
}
using var compilerLogStream = GetOrCreateCompilerLogStream(extra);
- var compilerCalls = CompilerLogUtil.ReadAllCompilerCalls(
- compilerLogStream,
- options.FilterCompilerCalls);
+ using var reader = GetCompilerLogReader(compilerLogStream, leaveOpen: true);
+ var compilerCalls = reader.ReadAllCompilerCalls(options.FilterCompilerCalls);
foreach (var compilerCall in compilerCalls)
{
@@ -350,7 +341,7 @@ int RunResponseFile(IEnumerable args)
return ExitSuccess;
}
- var compilerCalls = GetCompilerCalls(extra, options.FilterCompilerCalls);
+ var (disposable, compilerCalls) = GetCompilerCalls(extra, options.FilterCompilerCalls);
baseOutputPath = GetBaseOutputPath(baseOutputPath);
WriteLine($"Generating response files in {baseOutputPath}");
Directory.CreateDirectory(baseOutputPath);
@@ -365,6 +356,7 @@ int RunResponseFile(IEnumerable args)
ExportUtil.ExportRsp(compilerCall, writer, singleLine);
}
+ disposable.Dispose();
return ExitSuccess;
}
catch (OptionException e)
@@ -379,9 +371,26 @@ void PrintUsage()
WriteLine("complog rsp [OPTIONS] msbuild.complog");
options.WriteOptionDescriptions(Out);
}
+
+ (IDisposable disposable, List) GetCompilerCalls(List extra, Func? predicate)
+ {
+ var logFilePath = GetLogFilePath(extra);
+ var stream = new FileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ var ext = Path.GetExtension(logFilePath);
+ if (ext is ".binlog")
+ {
+ return (stream, BinaryLogUtil.ReadAllCompilerCalls(stream, new(), predicate));
+ }
+ else
+ {
+ Debug.Assert(ext is ".complog");
+ var reader = GetCompilerLogReader(stream, leaveOpen: false);
+ return (reader, reader.ReadAllCompilerCalls(predicate));
+ }
+ }
}
-int RunReplay(IEnumerable args, CancellationToken cancellationToken)
+int RunReplay(IEnumerable args)
{
var baseOutputPath = "";
var severity = DiagnosticSeverity.Warning;
@@ -428,8 +437,6 @@ int RunReplay(IEnumerable args, CancellationToken cancellationToken)
for (int i = 0; i < compilerCalls.Count; i++)
{
- cancellationToken.ThrowIfCancellationRequested();
-
var compilerCall = compilerCalls[i];
Write($"{compilerCall.GetDiagnosticName()} ...");
@@ -442,11 +449,11 @@ int RunReplay(IEnumerable args, CancellationToken cancellationToken)
{
var path = GetOutputPath(baseOutputPath, compilerCalls, i, "emit");
Directory.CreateDirectory(path);
- emitResult = compilationData.EmitToDisk(path, cancellationToken);
+ emitResult = compilationData.EmitToDisk(path);
}
else
{
- emitResult = compilationData.EmitToMemory(cancellationToken);
+ emitResult = compilationData.EmitToMemory();
}
WriteLine(emitResult.Success ? "Success" : "Error");
@@ -533,22 +540,6 @@ passed after --.
return ExitSuccess;
}
-List GetCompilerCalls(List extra, Func? predicate)
-{
- var logFilePath = GetLogFilePath(extra);
- using var stream = new FileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
- var ext = Path.GetExtension(logFilePath);
- switch (ext)
- {
- case ".binlog":
- return BinaryLogUtil.ReadAllCompilerCalls(stream, new(), predicate);
- case ".complog":
- return CompilerLogUtil.ReadAllCompilerCalls(stream, predicate);
- default:
- throw new Exception($"Unrecognized file extension: {ext}");
- }
-}
-
CompilerLogReader GetCompilerLogReader(Stream compilerLogStream, bool leaveOpen, BasicAnalyzerHostOptions? options = null)
{
var reader = CompilerLogReader.Create(compilerLogStream, leaveOpen, options);