feat(rust): Implement RustCargoLockParser and RustFingerprintScanner

- Added RustCargoLockParser to parse Cargo.lock files and extract package information.
- Introduced RustFingerprintScanner to scan for Rust fingerprint records in JSON files.
- Created test fixtures for Rust language analysis, including Cargo.lock and fingerprint JSON files.
- Developed tests for RustLanguageAnalyzer to ensure deterministic output based on provided fixtures.
- Added expected output files for both simple and signed Rust applications.
This commit is contained in:
master
2025-10-22 18:11:01 +03:00
parent c377229931
commit 35c5614eb7
66 changed files with 4200 additions and 217 deletions

View File

@@ -1,4 +1,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Scanner.Analyzers.Lang.DotNet;
using StellaOps.Scanner.Analyzers.Lang.Tests.Harness;
using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities;
@@ -25,4 +28,79 @@ public sealed class DotNetLanguageAnalyzerTests
analyzers,
cancellationToken);
}
[Fact]
public async Task SignedFixtureCapturesAssemblyMetadataAsync()
{
var cancellationToken = TestContext.Current.CancellationToken;
var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "signed");
var goldenPath = Path.Combine(fixturePath, "expected.json");
var analyzers = new ILanguageAnalyzer[]
{
new DotNetLanguageAnalyzer()
};
var inspector = new StubAuthenticodeInspector();
var services = new SingleServiceProvider(inspector);
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
fixturePath,
goldenPath,
analyzers,
cancellationToken,
usageHints: null,
services: services);
}
[Fact]
public async Task SelfContainedFixtureHandlesNativeAssetsAndUsageAsync()
{
var cancellationToken = TestContext.Current.CancellationToken;
var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "selfcontained");
var goldenPath = Path.Combine(fixturePath, "expected.json");
var usageHints = new LanguageUsageHints(new[]
{
Path.Combine(fixturePath, "lib", "net10.0", "StellaOps.Toolkit.dll"),
Path.Combine(fixturePath, "runtimes", "linux-x64", "native", "libstellaopsnative.so")
});
var analyzers = new ILanguageAnalyzer[]
{
new DotNetLanguageAnalyzer()
};
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
fixturePath,
goldenPath,
analyzers,
cancellationToken,
usageHints);
}
private sealed class StubAuthenticodeInspector : IDotNetAuthenticodeInspector
{
public DotNetAuthenticodeMetadata? TryInspect(string assemblyPath, CancellationToken cancellationToken)
=> new DotNetAuthenticodeMetadata(
Subject: "CN=StellaOps Test Signing",
Issuer: "CN=StellaOps Root",
NotBefore: new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero),
NotAfter: new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero),
Thumbprint: "AA11BB22CC33DD44EE55FF66GG77HH88II99JJ00",
SerialNumber: "0123456789ABCDEF");
}
private sealed class SingleServiceProvider : IServiceProvider
{
private readonly object _service;
public SingleServiceProvider(object service)
{
_service = service;
}
public object? GetService(Type serviceType)
=> serviceType == typeof(IDotNetAuthenticodeInspector) ? _service : null;
}
}

View File

@@ -0,0 +1,85 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": null
},
"targets": {
".NETCoreApp,Version=v10.0/linux-x64": {
"MyApp/1.0.0": {
"dependencies": {
"StellaOps.Toolkit": "1.2.3",
"StellaOps.Runtime.SelfContained": "2.1.0"
},
"runtime": {
"MyApp.dll": {}
}
},
"StellaOps.Toolkit/1.2.3": {
"runtime": {
"lib/net10.0/StellaOps.Toolkit.dll": {
"assemblyVersion": "1.2.3.0",
"fileVersion": "1.2.3.0"
}
}
},
"StellaOps.Runtime.SelfContained/2.1.0": {
"runtimeTargets": {
"runtimes/linux-x64/native/libstellaopsnative.so": {
"rid": "linux-x64",
"assetType": "native"
}
}
}
},
".NETCoreApp,Version=v10.0/win-x64": {
"MyApp/1.0.0": {
"dependencies": {
"StellaOps.Toolkit": "1.2.3",
"StellaOps.Runtime.SelfContained": "2.1.0"
},
"runtime": {
"MyApp.dll": {}
}
},
"StellaOps.Toolkit/1.2.3": {
"runtime": {
"lib/net10.0/StellaOps.Toolkit.dll": {
"assemblyVersion": "1.2.3.0",
"fileVersion": "1.2.3.0"
}
}
},
"StellaOps.Runtime.SelfContained/2.1.0": {
"runtimeTargets": {
"runtimes/win-x64/native/stellaopsnative.dll": {
"rid": "win-x64",
"assetType": "native"
}
}
}
}
},
"libraries": {
"MyApp/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": "",
"path": null,
"hashPath": null
},
"StellaOps.Toolkit/1.2.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FAKE_TOOLKIT_SHA==",
"path": "stellaops.toolkit/1.2.3",
"hashPath": "stellaops.toolkit.1.2.3.nupkg.sha512"
},
"StellaOps.Runtime.SelfContained/2.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FAKE_RUNTIME_SHA==",
"path": "stellaops.runtime.selfcontained/2.1.0",
"hashPath": "stellaops.runtime.selfcontained.2.1.0.nupkg.sha512"
}
}
}

View File

@@ -0,0 +1,15 @@
{
"runtimeOptions": {
"tfm": "net10.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "10.0.0"
},
"includedFrameworks": [
{
"name": "Microsoft.NETCore.DotNetAppHost",
"version": "10.0.0"
}
]
}
}

View File

@@ -0,0 +1,101 @@
[
{
"analyzerId": "dotnet",
"componentKey": "purl::pkg:nuget/stellaops.runtime.selfcontained@2.1.0",
"purl": "pkg:nuget/stellaops.runtime.selfcontained@2.1.0",
"name": "StellaOps.Runtime.SelfContained",
"version": "2.1.0",
"type": "nuget",
"usedByEntrypoint": true,
"metadata": {
"deps.path[0]": "MyApp.deps.json",
"deps.rid[0]": "linux-x64",
"deps.rid[1]": "win-x64",
"deps.tfm[0]": ".NETCoreApp,Version=v10.0",
"native[0].assetPath": "runtimes/linux-x64/native/libstellaopsnative.so",
"native[0].path": "runtimes/linux-x64/native/libstellaopsnative.so",
"native[0].rid[0]": "linux-x64",
"native[0].sha256": "c22d4a6584a3bb8fad4d255d1ab9e5a80d553eec35ea8dfcc2dd750e8581d3cb",
"native[0].tfm[0]": ".NETCoreApp,Version=v10.0",
"native[1].assetPath": "runtimes/win-x64/native/stellaopsnative.dll",
"native[1].path": "runtimes/win-x64/native/stellaopsnative.dll",
"native[1].rid[0]": "win-x64",
"native[1].sha256": "29cddd69702aedc715050304bec85aad2ae017ee1f9390df5e68ebe79a8d4745",
"native[1].tfm[0]": ".NETCoreApp,Version=v10.0",
"package.hashPath[0]": "stellaops.runtime.selfcontained.2.1.0.nupkg.sha512",
"package.id": "StellaOps.Runtime.SelfContained",
"package.id.normalized": "stellaops.runtime.selfcontained",
"package.path[0]": "stellaops.runtime.selfcontained/2.1.0",
"package.serviceable": "true",
"package.sha512[0]": "sha512-FAKE_RUNTIME_SHA==",
"package.version": "2.1.0"
},
"evidence": [
{
"kind": "file",
"source": "deps.json",
"locator": "MyApp.deps.json",
"value": "StellaOps.Runtime.SelfContained/2.1.0"
},
{
"kind": "file",
"source": "native",
"locator": "runtimes/linux-x64/native/libstellaopsnative.so",
"value": "runtimes/linux-x64/native/libstellaopsnative.so",
"sha256": "c22d4a6584a3bb8fad4d255d1ab9e5a80d553eec35ea8dfcc2dd750e8581d3cb"
},
{
"kind": "file",
"source": "native",
"locator": "runtimes/win-x64/native/stellaopsnative.dll",
"value": "runtimes/win-x64/native/stellaopsnative.dll",
"sha256": "29cddd69702aedc715050304bec85aad2ae017ee1f9390df5e68ebe79a8d4745"
}
]
},
{
"analyzerId": "dotnet",
"componentKey": "purl::pkg:nuget/stellaops.toolkit@1.2.3",
"purl": "pkg:nuget/stellaops.toolkit@1.2.3",
"name": "StellaOps.Toolkit",
"version": "1.2.3",
"type": "nuget",
"usedByEntrypoint": true,
"metadata": {
"assembly[0].assetPath": "lib/net10.0/StellaOps.Toolkit.dll",
"assembly[0].fileVersion": "1.2.3.0",
"assembly[0].path": "lib/net10.0/StellaOps.Toolkit.dll",
"assembly[0].rid[0]": "linux-x64",
"assembly[0].rid[1]": "win-x64",
"assembly[0].sha256": "5b82fd11cf6c2ba6b351592587c4203f6af48b89427b954903534eac0e9f17f7",
"assembly[0].tfm[0]": ".NETCoreApp,Version=v10.0",
"assembly[0].version": "1.2.3.0",
"deps.path[0]": "MyApp.deps.json",
"deps.rid[0]": "linux-x64",
"deps.rid[1]": "win-x64",
"deps.tfm[0]": ".NETCoreApp,Version=v10.0",
"package.hashPath[0]": "stellaops.toolkit.1.2.3.nupkg.sha512",
"package.id": "StellaOps.Toolkit",
"package.id.normalized": "stellaops.toolkit",
"package.path[0]": "stellaops.toolkit/1.2.3",
"package.serviceable": "true",
"package.sha512[0]": "sha512-FAKE_TOOLKIT_SHA==",
"package.version": "1.2.3"
},
"evidence": [
{
"kind": "file",
"source": "assembly",
"locator": "lib/net10.0/StellaOps.Toolkit.dll",
"value": "lib/net10.0/StellaOps.Toolkit.dll",
"sha256": "5b82fd11cf6c2ba6b351592587c4203f6af48b89427b954903534eac0e9f17f7"
},
{
"kind": "file",
"source": "deps.json",
"locator": "MyApp.deps.json",
"value": "StellaOps.Toolkit/1.2.3"
}
]
}
]

View File

@@ -0,0 +1,42 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0/linux-x64"
},
"targets": {
".NETCoreApp,Version=v10.0": {
"Signed.App/1.0.0": {
"dependencies": {
"Microsoft.Extensions.Logging": "9.0.0"
}
},
"Microsoft.Extensions.Logging/9.0.0": {
"runtime": {
"lib/net9.0/Microsoft.Extensions.Logging.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.24.52809"
}
}
}
},
".NETCoreApp,Version=v10.0/linux-x64": {
"Microsoft.Extensions.Logging/9.0.0": {
"runtime": {
"runtimes/linux-x64/lib/net9.0/Microsoft.Extensions.Logging.dll": {}
}
}
}
},
"libraries": {
"Signed.App/1.0.0": {
"type": "project",
"serviceable": false
},
"Microsoft.Extensions.Logging/9.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FAKE_LOGGING_SHA==",
"path": "microsoft.extensions.logging/9.0.0",
"hashPath": "microsoft.extensions.logging.9.0.0.nupkg.sha512"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"runtimeOptions": {
"tfm": "net10.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "10.0.0"
}
}
}

View File

@@ -0,0 +1,59 @@
[
{
"analyzerId": "dotnet",
"componentKey": "purl::pkg:nuget/microsoft.extensions.logging@9.0.0",
"purl": "pkg:nuget/microsoft.extensions.logging@9.0.0",
"name": "Microsoft.Extensions.Logging",
"version": "9.0.0",
"type": "nuget",
"usedByEntrypoint": false,
"metadata": {
"assembly[0].assetPath": "lib/net9.0/Microsoft.Extensions.Logging.dll",
"assembly[0].authenticode.issuer": "CN=StellaOps Root",
"assembly[0].authenticode.notAfter": "2026-01-01T00:00:00.000Z",
"assembly[0].authenticode.notBefore": "2025-01-01T00:00:00.000Z",
"assembly[0].authenticode.serialNumber": "0123456789ABCDEF",
"assembly[0].authenticode.subject": "CN=StellaOps Test Signing",
"assembly[0].authenticode.thumbprint": "AA11BB22CC33DD44EE55FF66GG77HH88II99JJ00",
"assembly[0].company": "Microsoft Corporation",
"assembly[0].fileDescription": "Microsoft.Extensions.Logging",
"assembly[0].fileVersion": "9.0.24.52809",
"assembly[0].path": "packages/microsoft.extensions.logging/9.0.0/lib/net9.0/Microsoft.Extensions.Logging.dll",
"assembly[0].product": "Microsoft\u00ae .NET",
"assembly[0].productVersion": "9.0.0+9d5a6a9aa463d6d10b0b0ba6d5982cc82f363dc3",
"assembly[0].publicKeyToken": "adb9793829ddae60",
"assembly[0].sha256": "faed6cb5c9ca0d6077feaeb2df251251adccf0241f7a80b91c58e014cd5ad48f",
"assembly[0].strongName": "Microsoft.Extensions.Logging, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
"assembly[0].tfm[0]": ".NETCoreApp,Version=v10.0",
"assembly[0].version": "9.0.0.0",
"assembly[1].assetPath": "runtimes/linux-x64/lib/net9.0/Microsoft.Extensions.Logging.dll",
"assembly[1].rid[0]": "linux-x64",
"assembly[1].tfm[0]": ".NETCoreApp,Version=v10.0",
"deps.path[0]": "Signed.App.deps.json",
"deps.rid[0]": "linux-x64",
"deps.tfm[0]": ".NETCoreApp,Version=v10.0",
"package.hashPath[0]": "microsoft.extensions.logging.9.0.0.nupkg.sha512",
"package.id": "Microsoft.Extensions.Logging",
"package.id.normalized": "microsoft.extensions.logging",
"package.path[0]": "microsoft.extensions.logging/9.0.0",
"package.serviceable": "true",
"package.sha512[0]": "sha512-FAKE_LOGGING_SHA==",
"package.version": "9.0.0"
},
"evidence": [
{
"kind": "file",
"source": "assembly",
"locator": "packages/microsoft.extensions.logging/9.0.0/lib/net9.0/Microsoft.Extensions.Logging.dll",
"value": "lib/net9.0/Microsoft.Extensions.Logging.dll",
"sha256": "faed6cb5c9ca0d6077feaeb2df251251adccf0241f7a80b91c58e014cd5ad48f"
},
{
"kind": "file",
"source": "deps.json",
"locator": "Signed.App.deps.json",
"value": "Microsoft.Extensions.Logging/9.0.0"
}
]
}
]

View File

@@ -8,6 +8,16 @@
"type": "nuget",
"usedByEntrypoint": false,
"metadata": {
"assembly[0].assetPath": "lib/net9.0/Microsoft.Extensions.Logging.dll",
"assembly[0].fileVersion": "9.0.24.52809",
"assembly[0].tfm[0]": ".NETCoreApp,Version=v10.0",
"assembly[0].version": "9.0.0.0",
"assembly[1].assetPath": "runtimes/linux-x64/lib/net9.0/Microsoft.Extensions.Logging.dll",
"assembly[1].rid[0]": "linux-x64",
"assembly[1].tfm[0]": ".NETCoreApp,Version=v10.0",
"assembly[2].assetPath": "runtimes/win-x86/lib/net9.0/Microsoft.Extensions.Logging.dll",
"assembly[2].rid[0]": "win-x86",
"assembly[2].tfm[0]": ".NETCoreApp,Version=v10.0",
"deps.path[0]": "Sample.App.deps.json",
"deps.rid[0]": "linux-x64",
"deps.rid[1]": "win-x86",
@@ -38,6 +48,10 @@
"type": "nuget",
"usedByEntrypoint": false,
"metadata": {
"assembly[0].assetPath": "lib/net10.0/StellaOps.Toolkit.dll",
"assembly[0].fileVersion": "1.2.3.0",
"assembly[0].tfm[0]": ".NETCoreApp,Version=v10.0",
"assembly[0].version": "1.2.3.0",
"deps.dependency[0]": "microsoft.extensions.logging",
"deps.path[0]": "Sample.App.deps.json",
"deps.rid[0]": "linux-x64",

View File

@@ -0,0 +1,12 @@
[[package]]
name = "my_app"
version = "0.1.0"
dependencies = [
"serde",
]
[[package]]
name = "serde"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abc123"

View File

@@ -0,0 +1,90 @@
[
{
"analyzerId": "rust",
"componentKey": "bin::sha256:22caa7413d89026b52db64c8abc254bf9e7647ab9216e79c6972a39451f8c41e",
"name": "unknown_tool",
"type": "bin",
"usedByEntrypoint": false,
"metadata": {
"binary.path": "usr/local/bin/unknown_tool",
"binary.sha256": "22caa7413d89026b52db64c8abc254bf9e7647ab9216e79c6972a39451f8c41e",
"provenance": "binary"
},
"evidence": [
{
"kind": "file",
"source": "binary",
"locator": "usr/local/bin/unknown_tool",
"sha256": "22caa7413d89026b52db64c8abc254bf9e7647ab9216e79c6972a39451f8c41e"
}
]
},
{
"analyzerId": "rust",
"componentKey": "purl::pkg:cargo/my_app@0.1.0",
"purl": "pkg:cargo/my_app@0.1.0",
"name": "my_app",
"version": "0.1.0",
"type": "cargo",
"usedByEntrypoint": true,
"metadata": {
"binary.paths": "usr/local/bin/my_app",
"binary.sha256": "a95a4f4854bf973deacbd937bd1189fc3d0eef7a4fd4f7960f37cf66162c82fd",
"cargo.lock.path": "Cargo.lock",
"fingerprint.profile": "debug",
"fingerprint.targetKind": "bin",
"source": "registry\u002Bhttps://github.com/rust-lang/crates.io-index"
},
"evidence": [
{
"kind": "file",
"source": "binary",
"locator": "usr/local/bin/my_app",
"sha256": "a95a4f4854bf973deacbd937bd1189fc3d0eef7a4fd4f7960f37cf66162c82fd"
},
{
"kind": "file",
"source": "cargo.fingerprint",
"locator": "target/debug/.fingerprint/my_app-1234567890abcdef/bin-my_app-1234567890abcdef.json",
"value": "bin"
},
{
"kind": "file",
"source": "cargo.lock",
"locator": "Cargo.lock",
"value": "my_app 0.1.0"
}
]
},
{
"analyzerId": "rust",
"componentKey": "purl::pkg:cargo/serde@1.0.188",
"purl": "pkg:cargo/serde@1.0.188",
"name": "serde",
"version": "1.0.188",
"type": "cargo",
"usedByEntrypoint": false,
"metadata": {
"cargo.lock.path": "Cargo.lock",
"checksum": "abc123",
"fingerprint.profile": "release",
"fingerprint.targetKind": "lib",
"source": "registry\u002Bhttps://github.com/rust-lang/crates.io-index"
},
"evidence": [
{
"kind": "file",
"source": "cargo.fingerprint",
"locator": "target/debug/.fingerprint/serde-abcdef1234567890/libserde-abcdef1234567890.json",
"value": "lib"
},
{
"kind": "file",
"source": "cargo.lock",
"locator": "Cargo.lock",
"value": "serde 1.0.188",
"sha256": "abc123"
}
]
}
]

View File

@@ -0,0 +1,5 @@
{
"pkgid": "my_app 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"profile": "debug",
"target_kind": ["bin"]
}

View File

@@ -0,0 +1,5 @@
{
"pkgid": "serde 1.0.188 (registry+https://github.com/rust-lang/crates.io-index)",
"profile": "release",
"target_kind": ["lib"]
}

View File

@@ -4,23 +4,23 @@ namespace StellaOps.Scanner.Analyzers.Lang.Tests.Harness;
public static class LanguageAnalyzerTestHarness
{
public static async Task<string> RunToJsonAsync(string fixturePath, IEnumerable<ILanguageAnalyzer> analyzers, CancellationToken cancellationToken = default, LanguageUsageHints? usageHints = null)
{
if (string.IsNullOrWhiteSpace(fixturePath))
{
throw new ArgumentException("Fixture path is required", nameof(fixturePath));
}
var engine = new LanguageAnalyzerEngine(analyzers ?? Array.Empty<ILanguageAnalyzer>());
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System, usageHints);
var result = await engine.AnalyzeAsync(context, cancellationToken).ConfigureAwait(false);
return result.ToJson(indent: true);
}
public static async Task AssertDeterministicAsync(string fixturePath, string goldenPath, IEnumerable<ILanguageAnalyzer> analyzers, CancellationToken cancellationToken = default, LanguageUsageHints? usageHints = null)
{
var actual = await RunToJsonAsync(fixturePath, analyzers, cancellationToken, usageHints).ConfigureAwait(false);
var expected = await File.ReadAllTextAsync(goldenPath, cancellationToken).ConfigureAwait(false);
public static async Task<string> RunToJsonAsync(string fixturePath, IEnumerable<ILanguageAnalyzer> analyzers, CancellationToken cancellationToken = default, LanguageUsageHints? usageHints = null, IServiceProvider? services = null)
{
if (string.IsNullOrWhiteSpace(fixturePath))
{
throw new ArgumentException("Fixture path is required", nameof(fixturePath));
}
var engine = new LanguageAnalyzerEngine(analyzers ?? Array.Empty<ILanguageAnalyzer>());
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System, usageHints, services);
var result = await engine.AnalyzeAsync(context, cancellationToken).ConfigureAwait(false);
return result.ToJson(indent: true);
}
public static async Task AssertDeterministicAsync(string fixturePath, string goldenPath, IEnumerable<ILanguageAnalyzer> analyzers, CancellationToken cancellationToken = default, LanguageUsageHints? usageHints = null, IServiceProvider? services = null)
{
var actual = await RunToJsonAsync(fixturePath, analyzers, cancellationToken, usageHints, services).ConfigureAwait(false);
var expected = await File.ReadAllTextAsync(goldenPath, cancellationToken).ConfigureAwait(false);
// Normalize newlines for portability.
actual = NormalizeLineEndings(actual).TrimEnd();

View File

@@ -0,0 +1,34 @@
using System.IO;
using StellaOps.Scanner.Analyzers.Lang.Rust;
using StellaOps.Scanner.Analyzers.Lang.Tests.Harness;
using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities;
namespace StellaOps.Scanner.Analyzers.Lang.Tests.Rust;
public sealed class RustLanguageAnalyzerTests
{
[Fact]
public async Task SimpleFixtureProducesDeterministicOutputAsync()
{
var cancellationToken = TestContext.Current.CancellationToken;
var fixturePath = TestPaths.ResolveFixture("lang", "rust", "simple");
var goldenPath = Path.Combine(fixturePath, "expected.json");
var usageHints = new LanguageUsageHints(new[]
{
Path.Combine(fixturePath, "usr/local/bin/my_app")
});
var analyzers = new ILanguageAnalyzer[]
{
new RustLanguageAnalyzer()
};
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
fixturePath,
goldenPath,
analyzers,
cancellationToken,
usageHints);
}
}

View File

@@ -32,6 +32,7 @@
<ItemGroup>
<ProjectReference Include="..\StellaOps.Scanner.Analyzers.Lang\StellaOps.Scanner.Analyzers.Lang.csproj" />
<ProjectReference Include="..\StellaOps.Scanner.Analyzers.Lang.DotNet\StellaOps.Scanner.Analyzers.Lang.DotNet.csproj" />
<ProjectReference Include="..\StellaOps.Scanner.Analyzers.Lang.Rust\StellaOps.Scanner.Analyzers.Lang.Rust.csproj" />
<ProjectReference Include="..\StellaOps.Scanner.Core\StellaOps.Scanner.Core.csproj" />
</ItemGroup>