Skip to content

Commit d754123

Browse files
committed
fix: align native library resolution reporting
1 parent f06c280 commit d754123

18 files changed

Lines changed: 1374 additions & 1317 deletions

Consyzer/AnalysisOrchestrator.cs

Lines changed: 121 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,121 @@
1-
using Microsoft.Extensions.Logging;
2-
using Consyzer.Analyzers;
3-
using Consyzer.Core.Models;
4-
using Consyzer.Output.Logging;
5-
using Consyzer.Output.Reporting;
6-
7-
namespace Consyzer;
8-
9-
internal sealed class AnalysisOrchestrator(
10-
ILogger<AnalysisOrchestrator> logger,
11-
IAnalysisLogBuilder analysisLogBuilder,
12-
IAnalyzer<IEnumerable<FileInfo>, AnalysisFileClassification> fileClassificationAnalyzer,
13-
IAnalyzer<IEnumerable<FileInfo>, IEnumerable<AssemblyMetadata>> metadataAnalyzer,
14-
IAnalyzer<IEnumerable<FileInfo>, IReadOnlyList<PInvokeMethodGroup>> pInvokeAnalyzer,
15-
IAnalyzer<IEnumerable<PInvokeMethodGroup>, IReadOnlyList<LibraryResolutionResult>> libraryResolutionAnalyzer,
16-
IAnalyzer<IEnumerable<LibraryResolutionResult>, AnalysisExitCode> exitCodeAnalyzer,
17-
IEnumerable<IReportWriter> reportWriters
18-
)
19-
{
20-
public ExitStatus Run(IReadOnlyList<FileInfo> files)
21-
{
22-
logger.LogInformation("Analysis started.");
23-
24-
if (logger.IsEnabled(LogLevel.Debug))
25-
{
26-
logger.LogDebug("{Message}", analysisLogBuilder.BuildFoundFilesLog(files));
27-
}
28-
29-
var fileClassification = fileClassificationAnalyzer.Analyze(files);
30-
if (logger.IsEnabled(LogLevel.Information))
31-
{
32-
logger.LogInformation("{Message}", analysisLogBuilder.BuildFileClassificationLog(fileClassification));
33-
}
34-
35-
var ecmaAssemblies = fileClassification.EcmaAssemblies.ToList();
36-
if (ecmaAssemblies.Count == 0)
37-
{
38-
logger.LogWarning("No valid ECMA assemblies found.");
39-
return ExitStatus.InvalidInput(InvalidInputReason.AllFilesInvalid);
40-
}
41-
42-
logger.LogInformation("Analyzing assembly metadata...");
43-
var metadataList = metadataAnalyzer.Analyze(ecmaAssemblies).ToList();
44-
45-
logger.LogInformation("Analyzing P/Invoke methods...");
46-
var pInvokeGroups = pInvokeAnalyzer.Analyze(ecmaAssemblies).ToList();
47-
48-
if (pInvokeGroups.Count == 0)
49-
{
50-
logger.LogWarning("No P/Invoke methods found in the assemblies.");
51-
return ExitStatus.InvalidInput(InvalidInputReason.NoPInvokeMethodsFound);
52-
}
53-
54-
logger.LogInformation("Analyzing native library resolution...");
55-
var libraryResolutions = libraryResolutionAnalyzer.Analyze(pInvokeGroups).ToList();
56-
57-
var summary = new AnalysisSummary
58-
{
59-
TotalFiles = files.Count,
60-
EcmaAssemblies = metadataList.Count,
61-
AssembliesWithPInvoke = pInvokeGroups.Count,
62-
TotalPInvokeMethods = pInvokeGroups.Sum(g => g.Methods.Count),
63-
ResolvedLibraries = libraryResolutions.Count(r => r.State == ResolutionState.Resolved),
64-
MissingLibraries = libraryResolutions.Count(r => r.State == ResolutionState.Missing),
65-
InconclusiveLibraries = libraryResolutions.Count(r => r.State == ResolutionState.Inconclusive)
66-
};
67-
68-
var outcome = new AnalysisOutcome
69-
{
70-
AssemblyMetadataList = metadataList,
71-
PInvokeMethodGroups = pInvokeGroups,
72-
LibraryResolutions = libraryResolutions,
73-
Summary = summary
74-
};
75-
76-
foreach (var writer in reportWriters)
77-
{
78-
if (logger.IsEnabled(LogLevel.Information))
79-
{
80-
logger.LogInformation("Generating report using {WriterType}...", writer.GetType().Name);
81-
}
82-
83-
var destination = writer.Write(outcome);
84-
if (logger.IsEnabled(LogLevel.Information))
85-
{
86-
logger.LogInformation("Report written to {Destination}.", destination);
87-
}
88-
}
89-
90-
var exitCode = exitCodeAnalyzer.Analyze(libraryResolutions);
91-
92-
var logLevel = GetExitCodeLogLevel(exitCode);
93-
if (logger.IsEnabled(logLevel))
94-
{
95-
logger.Log(
96-
logLevel,
97-
"Analysis completed with exit code {ExitCode}.",
98-
exitCode
99-
);
100-
}
101-
102-
return exitCode switch
103-
{
104-
AnalysisExitCode.Success => ExitStatus.Success(),
105-
AnalysisExitCode.Missing => ExitStatus.Missing(),
106-
AnalysisExitCode.Inconclusive => ExitStatus.Inconclusive(),
107-
AnalysisExitCode.ToolError => ExitStatus.ToolError(),
108-
_ => throw new InvalidOperationException($"Unsupported analysis exit code '{exitCode}'.")
109-
};
110-
}
111-
112-
private static LogLevel GetExitCodeLogLevel(AnalysisExitCode exitCode) =>
113-
exitCode switch
114-
{
115-
AnalysisExitCode.Success => LogLevel.Information,
116-
AnalysisExitCode.Missing => LogLevel.Warning,
117-
AnalysisExitCode.Inconclusive => LogLevel.Warning,
118-
AnalysisExitCode.InvalidInput => LogLevel.Warning,
119-
AnalysisExitCode.ToolError => LogLevel.Error,
120-
_ => LogLevel.Information
121-
};
122-
}
1+
using Microsoft.Extensions.Logging;
2+
using Consyzer.Analyzers;
3+
using Consyzer.Core.Models;
4+
using Consyzer.Output.Logging;
5+
using Consyzer.Output.Reporting;
6+
7+
namespace Consyzer;
8+
9+
internal sealed class AnalysisOrchestrator(
10+
ILogger<AnalysisOrchestrator> logger,
11+
IAnalysisLogBuilder analysisLogBuilder,
12+
IAnalyzer<IEnumerable<FileInfo>, AnalysisFileClassification> fileClassificationAnalyzer,
13+
IAnalyzer<IEnumerable<FileInfo>, IEnumerable<AssemblyMetadata>> metadataAnalyzer,
14+
IAnalyzer<IEnumerable<FileInfo>, IReadOnlyList<PInvokeMethodGroup>> pInvokeAnalyzer,
15+
IAnalyzer<IEnumerable<PInvokeMethodGroup>, IReadOnlyList<LibraryResolutionResult>> libraryResolutionAnalyzer,
16+
IAnalyzer<IEnumerable<LibraryResolutionResult>, AnalysisExitCode> exitCodeAnalyzer,
17+
IEnumerable<IReportWriter> reportWriters
18+
)
19+
{
20+
public ExitStatus Run(IReadOnlyList<FileInfo> files)
21+
{
22+
logger.LogInformation("Analysis started.");
23+
24+
if (logger.IsEnabled(LogLevel.Debug))
25+
{
26+
logger.LogDebug("{Message}", analysisLogBuilder.BuildFoundFilesLog(files));
27+
}
28+
29+
var fileClassification = fileClassificationAnalyzer.Analyze(files);
30+
if (logger.IsEnabled(LogLevel.Information))
31+
{
32+
logger.LogInformation("{Message}", analysisLogBuilder.BuildFileClassificationLog(fileClassification));
33+
}
34+
35+
var ecmaAssemblies = fileClassification.EcmaAssemblies.ToList();
36+
if (ecmaAssemblies.Count == 0)
37+
{
38+
logger.LogWarning("No valid ECMA assemblies found.");
39+
return ExitStatus.InvalidInput(InvalidInputReason.AllFilesInvalid);
40+
}
41+
42+
logger.LogInformation("Analyzing assembly metadata...");
43+
var metadataList = metadataAnalyzer.Analyze(ecmaAssemblies).ToList();
44+
45+
logger.LogInformation("Analyzing P/Invoke methods...");
46+
var pInvokeGroups = pInvokeAnalyzer.Analyze(ecmaAssemblies).ToList();
47+
48+
if (pInvokeGroups.Count == 0)
49+
{
50+
logger.LogInformation("No P/Invoke methods found in the assemblies.");
51+
}
52+
53+
logger.LogInformation("Analyzing native library resolution...");
54+
var libraryResolutions = libraryResolutionAnalyzer.Analyze(pInvokeGroups).ToList();
55+
56+
var summary = new AnalysisSummary
57+
{
58+
TotalFiles = files.Count,
59+
EcmaAssemblies = metadataList.Count,
60+
AssembliesWithPInvoke = pInvokeGroups.Count,
61+
TotalPInvokeMethods = pInvokeGroups.Sum(g => g.Methods.Count),
62+
ResolvedLibraries = libraryResolutions.Count(r => r.ResolutionState == ResolutionState.Resolved),
63+
MissingLibraries = libraryResolutions.Count(r => r.ResolutionState == ResolutionState.Missing),
64+
InconclusiveLibraries = libraryResolutions.Count(r => r.ResolutionState == ResolutionState.Inconclusive)
65+
};
66+
67+
var outcome = new AnalysisOutcome
68+
{
69+
AssemblyMetadataList = metadataList,
70+
PInvokeMethodGroups = pInvokeGroups,
71+
LibraryResolutions = libraryResolutions,
72+
Summary = summary
73+
};
74+
75+
foreach (var writer in reportWriters)
76+
{
77+
if (logger.IsEnabled(LogLevel.Information))
78+
{
79+
logger.LogInformation("Generating report using {WriterType}...", writer.GetType().Name);
80+
}
81+
82+
var destination = writer.Write(outcome);
83+
if (logger.IsEnabled(LogLevel.Information))
84+
{
85+
logger.LogInformation("Report written to {Destination}.", destination);
86+
}
87+
}
88+
89+
var exitCode = exitCodeAnalyzer.Analyze(libraryResolutions);
90+
91+
var logLevel = GetExitCodeLogLevel(exitCode);
92+
if (logger.IsEnabled(logLevel))
93+
{
94+
logger.Log(
95+
logLevel,
96+
"Analysis completed with exit code {ExitCode}.",
97+
exitCode
98+
);
99+
}
100+
101+
return exitCode switch
102+
{
103+
AnalysisExitCode.Success => ExitStatus.Success(),
104+
AnalysisExitCode.Missing => ExitStatus.Missing(),
105+
AnalysisExitCode.Inconclusive => ExitStatus.Inconclusive(),
106+
AnalysisExitCode.ToolError => ExitStatus.ToolError(),
107+
_ => throw new InvalidOperationException($"Unsupported analysis exit code '{exitCode}'.")
108+
};
109+
}
110+
111+
private static LogLevel GetExitCodeLogLevel(AnalysisExitCode exitCode) =>
112+
exitCode switch
113+
{
114+
AnalysisExitCode.Success => LogLevel.Information,
115+
AnalysisExitCode.Missing => LogLevel.Warning,
116+
AnalysisExitCode.Inconclusive => LogLevel.Warning,
117+
AnalysisExitCode.InvalidInput => LogLevel.Warning,
118+
AnalysisExitCode.ToolError => LogLevel.Error,
119+
_ => LogLevel.Information
120+
};
121+
}

Consyzer/Analyzers/AnalysisExitCodeAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public AnalysisExitCode Analyze(IEnumerable<LibraryResolutionResult> results)
1212

1313
foreach (var result in results)
1414
{
15-
switch (result.State)
15+
switch (result.ResolutionState)
1616
{
1717
case ResolutionState.Missing:
1818
hasMissing = true;

Consyzer/Analyzers/LibraryResolutionAnalyzer.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ IOptions<CommandLineOptions> options
1414
public IReadOnlyList<LibraryResolutionResult> Analyze(IEnumerable<PInvokeMethodGroup> methodGroups)
1515
{
1616
return [.. methodGroups
17-
.SelectMany(g => g.Methods)
18-
.Select(m => m.ImportName)
19-
.Distinct(StringComparer.OrdinalIgnoreCase)
20-
.Select(_resolver.Resolve)];
17+
.SelectMany(group => group.Methods
18+
.Select(method => method.ImportName)
19+
.Distinct(StringComparer.OrdinalIgnoreCase)
20+
.Select(libraryName => _resolver.Resolve(new LibraryResolutionContext(
21+
group.File,
22+
libraryName
23+
)))
24+
)
25+
];
2126
}
2227
}

0 commit comments

Comments
 (0)