diff --git a/src/Microsoft.ComponentDetection.Contracts/TypedComponent/SwiftComponent.cs b/src/Microsoft.ComponentDetection.Contracts/TypedComponent/SwiftComponent.cs
index ca516d022..de64905e1 100644
--- a/src/Microsoft.ComponentDetection.Contracts/TypedComponent/SwiftComponent.cs
+++ b/src/Microsoft.ComponentDetection.Contracts/TypedComponent/SwiftComponent.cs
@@ -11,29 +11,6 @@ namespace Microsoft.ComponentDetection.Contracts.TypedComponent;
///
public class SwiftComponent : TypedComponent
{
- ///
- /// Initializes a new instance of the class.
- ///
- /// The name of the component.
- /// The version of the component.
- /// The source repository URL of the component.
- /// The Git commit hash of the component.
- /// The Swift package kind.
- public SwiftComponent(string name, string version, string repositoryUrl, string hash, string kind)
- {
- this.Name = this.ValidateRequiredInput(name, nameof(name), nameof(ComponentType.Swift));
- this.Version = this.ValidateRequiredInput(version, nameof(version), nameof(ComponentType.Swift));
- this.ValidateRequiredInput(repositoryUrl, nameof(repositoryUrl), nameof(ComponentType.Swift));
- this.RepositoryUrl = new Uri(repositoryUrl);
- this.Kind = this.ValidateRequiredInput(kind, nameof(kind), nameof(ComponentType.Swift));
- this.CommitHash = this.ValidateRequiredInput(hash, nameof(hash), nameof(ComponentType.Swift));
- }
-
- public SwiftComponent()
- {
- /* Reserved for deserialization */
- }
-
[JsonPropertyName("name")]
public string Name { get; set; }
@@ -68,7 +45,7 @@ public SwiftComponent()
},
subpath: null);
- protected override string ComputeBaseId() => $"{this.RepositoryUrl.AbsoluteUri} {this.CommitHash} - {this.Type}";
+ protected override string ComputeBaseId() => $"{this.RepositoryUrl.AbsoluteUri} {this.Version} - {this.Type}";
private string GetNamespaceFromPackageUrl()
{
diff --git a/src/Microsoft.ComponentDetection.Detectors/swiftpm/SwiftResolvedComponentDetector.cs b/src/Microsoft.ComponentDetection.Detectors/swiftpm/SwiftResolvedComponentDetector.cs
index 241b7cbb3..d6cff8635 100644
--- a/src/Microsoft.ComponentDetection.Detectors/swiftpm/SwiftResolvedComponentDetector.cs
+++ b/src/Microsoft.ComponentDetection.Detectors/swiftpm/SwiftResolvedComponentDetector.cs
@@ -39,7 +39,7 @@ public SwiftResolvedComponentDetector(
public override IEnumerable SupportedComponentTypes => [ComponentType.Swift];
- public override int Version => 2;
+ public override int Version => 3;
protected override Task OnFileFoundAsync(
ProcessRequest processRequest,
@@ -77,15 +77,19 @@ private void ProcessPackageResolvedFile(ISingleFileComponentRecorder singleFileC
ArgumentException.ThrowIfNullOrWhiteSpace(package.Identity);
// The version of the package is not always available.
- var version = package.State.Version ?? package.State.Branch ?? package.State.Revision;
-
- var detectedComponent = new SwiftComponent(
- name: package.Identity,
- version: version,
- repositoryUrl: package.Location,
- hash: package.State.Revision,
- kind: package.Kind);
- singleFileComponentRecorder.RegisterUsage(new DetectedComponent(component: detectedComponent));
+ // For now when there's no version we don't report.
+ if (!string.IsNullOrWhiteSpace(package.State.Version))
+ {
+ var detectedComponent = new SwiftComponent
+ {
+ Name = package.Identity,
+ Version = package.State.Version,
+ RepositoryUrl = new Uri(package.Location),
+ CommitHash = package.State.Revision,
+ Kind = package.Kind,
+ };
+ singleFileComponentRecorder.RegisterUsage(new DetectedComponent(component: detectedComponent));
+ }
}
else
{
diff --git a/test/Microsoft.ComponentDetection.Contracts.Tests/TypedComponentSerializationTests.cs b/test/Microsoft.ComponentDetection.Contracts.Tests/TypedComponentSerializationTests.cs
index a351bd674..600fa1c8e 100644
--- a/test/Microsoft.ComponentDetection.Contracts.Tests/TypedComponentSerializationTests.cs
+++ b/test/Microsoft.ComponentDetection.Contracts.Tests/TypedComponentSerializationTests.cs
@@ -175,12 +175,14 @@ public void TypedComponent_Serialization_Git()
[TestMethod]
public void TypedComponent_Serialization_Swift()
{
- TypedComponent component = new SwiftComponent(
- "alamofire",
- "5.9.1",
- "https://github.com/Alamofire/Alamofire",
- "f455c2975872ccd2d9c81594c658af65716e9b9a",
- "remoteSourceControl");
+ TypedComponent component = new SwiftComponent
+ {
+ Name = "alamofire",
+ Version = "5.9.1",
+ RepositoryUrl = new Uri("https://github.com/Alamofire/Alamofire"),
+ CommitHash = "f455c2975872ccd2d9c81594c658af65716e9b9a",
+ Kind = "remoteSourceControl",
+ };
var json = JsonSerializer.Serialize(component);
var deserializedComponent = JsonSerializer.Deserialize(json);
diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/SwiftComponentTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/SwiftComponentTests.cs
index d0d75f0bd..085501ed1 100644
--- a/test/Microsoft.ComponentDetection.Detectors.Tests/SwiftComponentTests.cs
+++ b/test/Microsoft.ComponentDetection.Detectors.Tests/SwiftComponentTests.cs
@@ -21,7 +21,14 @@ public void Constructor_ShouldInitializeProperties()
var kind = "remoteSourceControl";
var commitHash = "f455c2975872ccd2d9c81594c658af65716e9b9a";
- var component = new SwiftComponent(name, version, repositoryUrl, commitHash, kind);
+ var component = new SwiftComponent
+ {
+ Name = name,
+ Version = version,
+ RepositoryUrl = new Uri(repositoryUrl),
+ CommitHash = commitHash,
+ Kind = kind,
+ };
component.Name.Should().Be(name);
component.Version.Should().Be(version);
@@ -30,45 +37,44 @@ public void Constructor_ShouldInitializeProperties()
component.RepositoryUrl.Should().Be(new Uri(repositoryUrl));
component.Type.Should().Be(ComponentType.Swift);
component.Id.Should().Be(
- $"{repositoryUrl} {commitHash} - {component.Type}");
+ $"{repositoryUrl} {version} - {component.Type}");
}
[TestMethod]
- public void Id_ShouldDistinguishRepositoriesAndCommitHashes()
+ public void Id_ShouldDistinguishRepositories()
{
- var component = new SwiftComponent(
- "alamofire",
- "5.9.1",
- "https://github.com/Alamofire/Alamofire",
- "f455c2975872ccd2d9c81594c658af65716e9b9a",
- "remoteSourceControl");
- var differentRepository = new SwiftComponent(
- "alamofire",
- "5.9.1",
- "https://github.com/example/Alamofire",
- "f455c2975872ccd2d9c81594c658af65716e9b9a",
- "remoteSourceControl");
- var differentCommit = new SwiftComponent(
- "alamofire",
- "5.9.1",
- "https://github.com/Alamofire/Alamofire",
- "63dfa86548c4e5d5c6fd6ed42f638e388cbce529",
- "remoteSourceControl");
+ var component = new SwiftComponent
+ {
+ Name = "alamofire",
+ Version = "5.9.1",
+ RepositoryUrl = new Uri("https://github.com/Alamofire/Alamofire"),
+ CommitHash = "f455c2975872ccd2d9c81594c658af65716e9b9a",
+ Kind = "remoteSourceControl",
+ };
+ var differentRepository = new SwiftComponent
+ {
+ Name = "alamofire",
+ Version = "5.9.1",
+ RepositoryUrl = new Uri("https://github.com/example/Alamofire"),
+ CommitHash = "f455c2975872ccd2d9c81594c658af65716e9b9a",
+ Kind = "remoteSourceControl",
+ };
component.Id.Should().NotBe(differentRepository.Id);
- component.Id.Should().NotBe(differentCommit.Id);
}
[TestMethod]
public void Serialization_ShouldIncludeCommitHash()
{
var commitHash = "f455c2975872ccd2d9c81594c658af65716e9b9a";
- TypedComponent component = new SwiftComponent(
- name: "alamofire",
- version: "5.9.1",
- repositoryUrl: "https://github.com/Alamofire/Alamofire",
- hash: commitHash,
- kind: "remoteSourceControl");
+ TypedComponent component = new SwiftComponent
+ {
+ Name = "alamofire",
+ Version = "5.9.1",
+ RepositoryUrl = new Uri("https://github.com/Alamofire/Alamofire"),
+ CommitHash = commitHash,
+ Kind = "remoteSourceControl",
+ };
using var json = JsonDocument.Parse(JsonSerializer.Serialize(component));
@@ -76,90 +82,6 @@ public void Serialization_ShouldIncludeCommitHash()
json.RootElement.GetProperty("commitHash").GetString().Should().Be(commitHash);
}
- [TestMethod]
- public void Constructor_ShouldThrowException_WhenKindIsNull()
- {
- Action action = () =>
- new SwiftComponent(
- "alamofire",
- "5.9.1",
- "https://github.com/Alamofire/Alamofire",
- "f455c2975872ccd2d9c81594c658af65716e9b9a",
- null
- );
- action.Should().Throw().WithMessage("*kind*");
- }
-
- [TestMethod]
- public void Constructor_ShouldThrowException_WhenNameIsNull()
- {
- Action action = () =>
- new SwiftComponent(
- null,
- "5.9.1",
- "https://github.com/Alamofire/Alamofire",
- "f455c2975872ccd2d9c81594c658af65716e9b9a",
- "remoteSourceControl"
- );
- action.Should().Throw().WithMessage("*name*");
- }
-
- [TestMethod]
- public void Constructor_ShouldThrowException_WhenVersionIsNull()
- {
- Action action = () =>
- new SwiftComponent(
- "alamofire",
- null,
- "https://github.com/Alamofire/Alamofire",
- "f455c2975872ccd2d9c81594c658af65716e9b9a",
- "remoteSourceControl"
- );
- action.Should().Throw().WithMessage("*version*");
- }
-
- [TestMethod]
- public void Constructor_ShouldThrowException_WhenRepositoryUrlIsNull()
- {
- Action action = () =>
- new SwiftComponent(
- "alamofire",
- "5.9.1",
- null,
- "f455c2975872ccd2d9c81594c658af65716e9b9a",
- "remoteSourceControl"
- );
- action.Should().Throw().WithMessage("*repositoryUrl*");
- }
-
- [TestMethod]
- public void Constructor_ShouldThrowException_WhenHashIsNull()
- {
- Action action = () =>
- new SwiftComponent(
- "alamofire",
- "5.9.1",
- "https://github.com/Alamofire/Alamofire",
- null,
- "remoteSourceControl"
- );
- action.Should().Throw().WithMessage("*hash*");
- }
-
- [TestMethod]
- public void Constructor_ShouldThrowException_WhenRepositoryUrlIsInvalid()
- {
- Action action = () =>
- new SwiftComponent(
- "alamofire",
- "5.9.1",
- "invalid-url",
- "f455c2975872ccd2d9c81594c658af65716e9b9a",
- "remoteSourceControl"
- );
- action.Should().Throw();
- }
-
[TestMethod]
public void PackageURL_ShouldReturnCorrectPackageURL_GithubHostname()
{
@@ -168,7 +90,14 @@ public void PackageURL_ShouldReturnCorrectPackageURL_GithubHostname()
var repositoryUrl = "https://github.com/Alamofire/Alamofire";
var hash = "f455c2975872ccd2d9c81594c658af65716e9b9a";
- var component = new SwiftComponent(name, version, repositoryUrl, hash, "remoteSourceControl");
+ var component = new SwiftComponent
+ {
+ Name = name,
+ Version = version,
+ RepositoryUrl = new Uri(repositoryUrl),
+ CommitHash = hash,
+ Kind = "remoteSourceControl",
+ };
var expectedPackageURL = new PackageURL(
type: "swift",
@@ -190,7 +119,14 @@ public void PackageURL_ShouldReturnCorrectPackageURL_GithubHostname_Alternate()
var repositoryUrl = "https://giTHub.com/Alamofire/Alamofire";
var hash = "f455c2975872ccd2d9c81594c658af65716e9b9a";
- var component = new SwiftComponent(name, version, repositoryUrl, hash, "remoteSourceControl");
+ var component = new SwiftComponent
+ {
+ Name = name,
+ Version = version,
+ RepositoryUrl = new Uri(repositoryUrl),
+ CommitHash = hash,
+ Kind = "remoteSourceControl",
+ };
var expectedPackageURL = new PackageURL(
type: "swift",
@@ -215,7 +151,14 @@ public void PackageURL_ShouldReturnCorrectPackageURL_OtherHostname()
var repositoryUrl = "https://otherhostname.com/Alamofire/Alamofire";
var hash = "f455c2975872ccd2d9c81594c658af65716e9b9a";
- var component = new SwiftComponent(name, version, repositoryUrl, hash, "remoteSourceControl");
+ var component = new SwiftComponent
+ {
+ Name = name,
+ Version = version,
+ RepositoryUrl = new Uri(repositoryUrl),
+ CommitHash = hash,
+ Kind = "remoteSourceControl",
+ };
var expectedPackageURL = new PackageURL(
type: "swift",
diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/SwiftResolvedDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/SwiftResolvedDetectorTests.cs
index e8f13b0eb..25322b00a 100644
--- a/test/Microsoft.ComponentDetection.Detectors.Tests/SwiftResolvedDetectorTests.cs
+++ b/test/Microsoft.ComponentDetection.Detectors.Tests/SwiftResolvedDetectorTests.cs
@@ -1,6 +1,7 @@
#nullable disable
namespace Microsoft.ComponentDetection.Detectors.Tests.Swift;
+using System;
using System.Linq;
using System.Threading.Tasks;
using AwesomeAssertions;
@@ -48,12 +49,14 @@ public async Task Test_GivenDetectorWithValidFile_WhenScan_ThenScanIsSuccessfulA
var typedComponents = detectedComponents.Select(c => c.Component).ToList();
typedComponents.Should().ContainEquivalentOf(
- new SwiftComponent(
- name: "alamofire",
- version: "5.9.1",
- repositoryUrl: "https://github.com/Alamofire/Alamofire",
- hash: "f455c2975872ccd2d9c81594c658af65716e9b9a",
- kind: "remoteSourceControl"));
+ new SwiftComponent
+ {
+ Name = "alamofire",
+ Version = "5.9.1",
+ RepositoryUrl = new Uri("https://github.com/Alamofire/Alamofire"),
+ CommitHash = "f455c2975872ccd2d9c81594c658af65716e9b9a",
+ Kind = "remoteSourceControl",
+ });
}
// Test for several packages
@@ -76,20 +79,24 @@ public async Task Test_GivenDetectorWithValidFileWithMultiplePackages_WhenScan_T
var typedComponents = detectedComponents.Select(c => c.Component).ToList();
typedComponents.Should().ContainEquivalentOf(
- new SwiftComponent(
- name: "alamofire",
- version: "5.6.0",
- repositoryUrl: "https://github.com/Alamofire/Alamofire",
- hash: "63dfa86548c4e5d5c6fd6ed42f638e388cbce529",
- kind: "remoteSourceControl"));
+ new SwiftComponent
+ {
+ Name = "alamofire",
+ Version = "5.6.0",
+ RepositoryUrl = new Uri("https://github.com/Alamofire/Alamofire"),
+ CommitHash = "63dfa86548c4e5d5c6fd6ed42f638e388cbce529",
+ Kind = "remoteSourceControl",
+ });
typedComponents.Should().ContainEquivalentOf(
- new SwiftComponent(
- name: "asyncextensions",
- version: "0.5.3",
- repositoryUrl: "https://github.com/sideeffect-io/AsyncExtensions",
- hash: "3442d3d046800f1974bda096faaf0ac510b21154",
- kind: "remoteSourceControl"));
+ new SwiftComponent
+ {
+ Name = "asyncextensions",
+ Version = "0.5.3",
+ RepositoryUrl = new Uri("https://github.com/sideeffect-io/AsyncExtensions"),
+ CommitHash = "3442d3d046800f1974bda096faaf0ac510b21154",
+ Kind = "remoteSourceControl",
+ });
}
// Duplicate packages
@@ -137,12 +144,14 @@ public async Task Test_GivenDetectorWithValidFileWithDuplicatePackages_WhenScan_
var typedComponents = detectedComponents.Select(c => c.Component).ToList();
typedComponents.Should().ContainEquivalentOf(
- new SwiftComponent(
- name: "alamofire",
- version: "5.9.1",
- repositoryUrl: "https://github.com/Alamofire/Alamofire",
- hash: "f455c2975872ccd2d9c81594c658af65716e9b9a",
- kind: "remoteSourceControl"));
+ new SwiftComponent
+ {
+ Name = "alamofire",
+ Version = "5.9.1",
+ RepositoryUrl = new Uri("https://github.com/Alamofire/Alamofire"),
+ CommitHash = "f455c2975872ccd2d9c81594c658af65716e9b9a",
+ Kind = "remoteSourceControl",
+ });
}
[TestMethod]
@@ -340,7 +349,7 @@ public async Task Test_GivenResolvedPackageWithEmptyState_WhenScan_ThenScanIsSuc
}
[TestMethod]
- public async Task Test_GivenResolvedPackageWithoutRevision_WhenScan_ThenScanIsSuccessfulAndNoComponentsRegistered()
+ public async Task Test_GivenResolvedPackageWithoutRevision_WhenScan_ThenScanIsSuccessfulAndComponentsRegistered()
{
var resolvedPackageWithoutRevision = """
{
@@ -364,11 +373,11 @@ public async Task Test_GivenResolvedPackageWithoutRevision_WhenScan_ThenScanIsSu
.ExecuteDetectorAsync();
scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
- componentRecorder.GetDetectedComponents().Should().BeEmpty();
+ componentRecorder.GetDetectedComponents().Should().HaveCount(1);
}
[TestMethod]
- public async Task Test_GivenResolvedPackageWithoutVersion_WhenScan_ThenScanIsSuccessfulAndComponentRegisteredWithRevisionHashAsVersion()
+ public async Task Test_GivenResolvedPackageWithoutVersion_WhenScan_ThenScanIsSuccessfulAndNoComponentRegistered()
{
var resolvedPackageWithoutVersion = """
{
@@ -392,18 +401,7 @@ public async Task Test_GivenResolvedPackageWithoutVersion_WhenScan_ThenScanIsSuc
.ExecuteDetectorAsync();
scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
- componentRecorder.GetDetectedComponents().Should().ContainSingle();
-
- var detectedComponents = componentRecorder.GetDetectedComponents();
- var typedComponents = detectedComponents.Select(c => c.Component).ToList();
-
- typedComponents.Should().ContainEquivalentOf(
- new SwiftComponent(
- name: "alamofire",
- version: "f455c2975872ccd2d9c81594c658af65716e9b9a",
- repositoryUrl: "https://github.com/Alamofire/Alamofire",
- hash: "f455c2975872ccd2d9c81594c658af65716e9b9a",
- kind: "remoteSourceControl"));
+ componentRecorder.GetDetectedComponents().Should().BeEmpty();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "Test data that is better placed at the end of the file.")]