Add Ruby language analyzer and related functionality

- Introduced global usings for Ruby analyzer.
- Implemented RubyLockData, RubyLockEntry, and RubyLockParser for handling Gemfile.lock files.
- Created RubyPackage and RubyPackageCollector to manage Ruby packages and vendor cache.
- Developed RubyAnalyzerPlugin and RubyLanguageAnalyzer for analyzing Ruby projects.
- Added tests for Ruby language analyzer with sample Gemfile.lock and expected output.
- Included necessary project files and references for the Ruby analyzer.
- Added third-party licenses for tree-sitter dependencies.
This commit is contained in:
master
2025-11-03 01:15:43 +02:00
parent ff0eca3a51
commit bf2bf4b395
88 changed files with 6557 additions and 1568 deletions

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace StellaOps.AdvisoryAI.Tools;
/// <summary>
/// Summarises dependency graph characteristics used by deterministic tooling.
/// </summary>
public sealed class DependencyAnalysisResult
{
private DependencyAnalysisResult(
string artifactId,
ImmutableArray<DependencyNodeSummary> nodes,
ImmutableDictionary<string, string> metadata)
{
ArtifactId = artifactId;
Nodes = nodes;
Metadata = metadata;
}
public string ArtifactId { get; }
public ImmutableArray<DependencyNodeSummary> Nodes { get; }
public ImmutableDictionary<string, string> Metadata { get; }
public static DependencyAnalysisResult Create(
string artifactId,
IEnumerable<DependencyNodeSummary> nodes,
IReadOnlyDictionary<string, string> metadata)
{
ArgumentException.ThrowIfNullOrWhiteSpace(artifactId);
ArgumentNullException.ThrowIfNull(nodes);
ArgumentNullException.ThrowIfNull(metadata);
return new DependencyAnalysisResult(
artifactId.Trim(),
nodes.ToImmutableArray(),
metadata.ToImmutableDictionary(StringComparer.Ordinal));
}
public static DependencyAnalysisResult Empty(string artifactId)
=> new DependencyAnalysisResult(
artifactId?.Trim() ?? string.Empty,
ImmutableArray<DependencyNodeSummary>.Empty,
ImmutableDictionary<string, string>.Empty);
}
public sealed class DependencyNodeSummary
{
public DependencyNodeSummary(
string identifier,
IReadOnlyList<string> versions,
int runtimeOccurrences,
int developmentOccurrences)
{
ArgumentException.ThrowIfNullOrWhiteSpace(identifier);
Identifier = identifier.Trim();
Versions = versions?.ToImmutableArray() ?? ImmutableArray<string>.Empty;
RuntimeOccurrences = Math.Max(runtimeOccurrences, 0);
DevelopmentOccurrences = Math.Max(developmentOccurrences, 0);
}
public string Identifier { get; }
public ImmutableArray<string> Versions { get; }
public int RuntimeOccurrences { get; }
public int DevelopmentOccurrences { get; }
}
internal sealed class NodeAccumulator
{
public string Identifier { get; set; } = string.Empty;
public HashSet<string> Versions { get; set; } = new(StringComparer.Ordinal);
public int RuntimeOccurrences { get; set; }
public int DevelopmentOccurrences { get; set; }
}