Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: CI

# Trigger the workflow on pushes to main branches and pull requests
on:
push:
branches:
- main
- master
- develop
pull_request:
branches:
- main
- master
- develop

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
# Step 1: Checkout the repository
- name: Checkout repository
uses: actions/checkout@v4

# Step 2: Setup .NET SDK
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'

# Step 3: Restore dependencies
- name: Restore dependencies
run: dotnet restore

# Step 4: Build the project
- name: Build
run: dotnet build --configuration Release --no-restore

# Step 5: Run tests
- name: Test
run: dotnet test --configuration Release --no-build --verbosity normal --collect:"XPlat Code Coverage"

# Step 6: Upload test results
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: '**/TestResults/**/*'

# Step 7: Build summary
- name: Build Summary
if: always()
run: |
echo "### Build Summary :rocket:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Status**: ${{ job.status }}" >> $GITHUB_STEP_SUMMARY
echo "- **Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
4 changes: 2 additions & 2 deletions .github/workflows/csharp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ jobs:
steps:
# Step 1: Checkout the repository
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

# Step 2: Setup .NET SDK
- name: Setup .NET
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x' # Updated to match your project

Expand Down
22 changes: 12 additions & 10 deletions Foundation.Data.Doublets.Cli/AdvancedMixedQueryProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public class Options

public static void ProcessQuery(NamedLinksDecorator<uint> links, Options options)
{
ArgumentNullException.ThrowIfNull(links);
ArgumentNullException.ThrowIfNull(options);

var query = options.Query;
TraceIfEnabled(options, $"[ProcessQuery] Query: \"{query}\"");

Expand Down Expand Up @@ -93,16 +96,18 @@ public static void ProcessQuery(NamedLinksDecorator<uint> links, Options options
.ToList();

// ----------------------------------------------------------------
// FIX: If we see restrictionLink with exactly 1 sub-link => that sub-link has 2 sub-values => no IDs => interpret as a single composite pattern
// FIX: If we see restrictionLink with exactly 1 sub-link => that sub-link has 2 sub-values => interpret as a single composite pattern
// This handles patterns like ((() (1 2))) where the outer restriction has a single composite child
if (
string.IsNullOrEmpty(restrictionLink.Id) &&
restrictionLink.Values?.Count == 1
)
{
var single = restrictionLink.Values[0];
// Check if this is a composite (has 2 sub-values) and doesn't have a numeric/wildcard ID
if (
string.IsNullOrEmpty(single.Id) &&
single.Values?.Count == 2 && !IsNumericOrStar(single.Id)
single.Values?.Count == 2 &&
(string.IsNullOrEmpty(single.Id) || !IsNumericOrStar(single.Id))
)
{
// Create a single composite pattern from ((1 *) (* 2))
Expand All @@ -120,7 +125,7 @@ public static void ProcessQuery(NamedLinksDecorator<uint> links, Options options
restrictionInternalPatterns.Add(topLevelPattern);

TraceIfEnabled(options,
"[ProcessQuery] Detected single sub-link (no ID) with 2 sub-values => replaced with one composite restriction pattern.");
"[ProcessQuery] Detected single sub-link with 2 sub-values => replaced with one composite restriction pattern.");
}
}
// ----------------------------------------------------------------
Expand Down Expand Up @@ -659,9 +664,10 @@ private static uint ResolveId(
{
return anyConstant;
}
if (TryParseLinkId(identifier, links.Constants, ref anyConstant))
uint parsedValue = anyConstant;
if (TryParseLinkId(identifier, links.Constants, ref parsedValue))
{
return anyConstant;
return parsedValue;
}
// Add name resolution for deletion patterns
var namedId = links.GetByName(identifier);
Expand Down Expand Up @@ -800,10 +806,6 @@ private static void CreateOrUpdateLink(NamedLinksDecorator<uint> links, DoubletL
TraceIfEnabled(options,
$"[CreateOrUpdateLink] Updating link #{linkDefinition.Index}: {existingDoublet.Source}->{linkDefinition.Source}, {existingDoublet.Target}->{linkDefinition.Target}.");
LinksExtensions.EnsureCreated(links, linkDefinition.Index);
options.ChangesHandler?.Invoke(
new DoubletLink(linkDefinition.Index, nullConstant, nullConstant),
new DoubletLink(linkDefinition.Index, nullConstant, nullConstant)
);
links.Update(
new DoubletLink(linkDefinition.Index, anyConstant, anyConstant),
linkDefinition,
Expand Down
137 changes: 70 additions & 67 deletions Foundation.Data.Doublets.Cli/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,81 +1,84 @@
using System;
using System.Collections.Generic;

public static class EnumerableExtensions
namespace Foundation.Data.Doublets.Cli
{
public static void Deconstruct<T>(this IEnumerable<T> source, out T first)
public static class EnumerableExtensions
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
}
public static void Deconstruct<T>(this IEnumerable<T> source, out T first)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
}

public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
}
public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
}

public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
}
public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
}

public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
}
public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
}

public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth, out T fifth)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
fifth = enumerator.MoveNext() ? enumerator.Current : default!;
}
public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth, out T fifth)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
fifth = enumerator.MoveNext() ? enumerator.Current : default!;
}

public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth, out T fifth, out T sixth)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
fifth = enumerator.MoveNext() ? enumerator.Current : default!;
sixth = enumerator.MoveNext() ? enumerator.Current : default!;
}
public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth, out T fifth, out T sixth)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
fifth = enumerator.MoveNext() ? enumerator.Current : default!;
sixth = enumerator.MoveNext() ? enumerator.Current : default!;
}

public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth, out T fifth, out T sixth, out T seventh)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
fifth = enumerator.MoveNext() ? enumerator.Current : default!;
sixth = enumerator.MoveNext() ? enumerator.Current : default!;
seventh = enumerator.MoveNext() ? enumerator.Current : default!;
}
public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth, out T fifth, out T sixth, out T seventh)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
fifth = enumerator.MoveNext() ? enumerator.Current : default!;
sixth = enumerator.MoveNext() ? enumerator.Current : default!;
seventh = enumerator.MoveNext() ? enumerator.Current : default!;
}

public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth, out T fifth, out T sixth, out T seventh, out T eighth)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
fifth = enumerator.MoveNext() ? enumerator.Current : default!;
sixth = enumerator.MoveNext() ? enumerator.Current : default!;
seventh = enumerator.MoveNext() ? enumerator.Current : default!;
eighth = enumerator.MoveNext() ? enumerator.Current : default!;
public static void Deconstruct<T>(this IEnumerable<T> source, out T first, out T second, out T third, out T fourth, out T fifth, out T sixth, out T seventh, out T eighth)
{
using var enumerator = source.GetEnumerator();
first = enumerator.MoveNext() ? enumerator.Current : default!;
second = enumerator.MoveNext() ? enumerator.Current : default!;
third = enumerator.MoveNext() ? enumerator.Current : default!;
fourth = enumerator.MoveNext() ? enumerator.Current : default!;
fifth = enumerator.MoveNext() ? enumerator.Current : default!;
sixth = enumerator.MoveNext() ? enumerator.Current : default!;
seventh = enumerator.MoveNext() ? enumerator.Current : default!;
eighth = enumerator.MoveNext() ? enumerator.Current : default!;
}
}
}
49 changes: 49 additions & 0 deletions Foundation.Data.Doublets.Cli/Exceptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;

namespace Foundation.Data.Doublets.Cli
{
/// <summary>
/// Exception thrown when a link has an invalid format or structure.
/// </summary>
public class InvalidLinkFormatException : Exception
{
public InvalidLinkFormatException(string message) : base(message)
{
}

public InvalidLinkFormatException(string message, Exception innerException)
: base(message, innerException)
{
}
}

/// <summary>
/// Exception thrown when a link structure doesn't match expected patterns.
/// </summary>
public class UnexpectedLinkStructureException : InvalidOperationException
{
public UnexpectedLinkStructureException(string message) : base(message)
{
}

public UnexpectedLinkStructureException(string message, Exception innerException)
: base(message, innerException)
{
}
}

/// <summary>
/// Exception thrown when a query pattern is invalid or cannot be processed.
/// </summary>
public class InvalidQueryPatternException : Exception
{
public InvalidQueryPatternException(string message) : base(message)
{
}

public InvalidQueryPatternException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}
Loading
Loading