Skip to content

Feature/identification#51

Merged
hugener merged 23 commits into
mainfrom
feature/Identification
May 2, 2026
Merged

Feature/identification#51
hugener merged 23 commits into
mainfrom
feature/Identification

Conversation

@hugener
Copy link
Copy Markdown
Collaborator

@hugener hugener commented May 2, 2026

No description provided.

hugener added 12 commits March 9, 2026 00:13
…undew.Base into feature/Identification

# Conflicts:
#	Source/Sundew.Base.Identification/IValueIdentifiable.cs
#	Source/Sundew.Base.Identification/Path.cs
#	Source/Sundew.Base.Identification/Source.cs
#	Source/Sundew.Base.Identification/Sundew.Base.Identification.csproj
#	Source/Sundew.Base.Identification/Target.cs
#	Source/Sundew.Base.Identification/TargetEvaluator.cs
#	Source/Sundew.Base.Identification/ValueIdBuilder.cs
Partial support for InstanceIds in ValueId
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new identification/parsing feature set to the Sundew.Base codebase, adds supporting result/collection changes needed by that feature, and expands the test project to cover parts of the new API surface.

Changes:

  • Add new Sundew.Base.Identification and Sundew.Base.Parsing projects with ID, value, target, lexer, and parser primitives.
  • Extend result/union-related primitives and collection equality behavior to support the new APIs and newer discriminated-union generation.
  • Update tests, solution/project wiring, and central package versions to include the new feature area.

Reviewed changes

Copilot reviewed 69 out of 70 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
Source/Sundew.Base.slnx Adds the new Identification and Parsing projects to the solution.
Source/Sundew.Base.Threading/ValueSynchronizer.cs Removes a stale commented line in cancellation handling.
Source/Sundew.Base.Threading/PostSubmitAction.cs Marks nested records as partial for source-generation compatibility.
Source/Sundew.Base.Primitives/Sundew.Base.Primitives.csproj Normalizes package reference formatting.
Source/Sundew.Base.Primitives/R{TSuccess}.cs Adds true/false operators to the success-only result type.
Source/Sundew.Base.Primitives/R{TSuccess,TError}.cs Replaces implicit bool conversion with true/false operators.
Source/Sundew.Base.Primitives/RoE{TError}.cs Adds true/false operators to the error-only result type.
Source/Sundew.Base.Primitives/ResultOfErrorExtensions.cs Adds RoE chaining helpers via extension blocks.
Source/Sundew.Base.Primitives/ResultExtensions.cs Adds And combinators for composing result tuples.
Source/Sundew.Base.Primitives/Failure.cs Marks union records as partial.
Source/Sundew.Base.Parsing/Sundew.Base.Parsing.csproj Adds the new Parsing library project.
Source/Sundew.Base.Parsing/RegexLexerRule.cs Implements regex-backed lexer rules.
Source/Sundew.Base.Parsing/ParserDebugView.cs Adds a debugger proxy for parser state inspection.
Source/Sundew.Base.Parsing/Parser.cs Introduces the core parser state machine and accept/undo helpers.
Source/Sundew.Base.Parsing/ParseSettings.cs Adds parse settings configuration type.
Source/Sundew.Base.Parsing/LexerError.cs Defines lexer error union types.
Source/Sundew.Base.Parsing/Lexer.cs Implements token-to-rule dispatch for lexing.
Source/Sundew.Base.Parsing/ILexerRule.cs Defines the lexer rule contract.
Source/Sundew.Base.Parsing/ILexer.cs Defines the lexer contract.
Source/Sundew.Base.Identification/ValueIdBuilder.cs Builds ValueId instances from object members.
Source/Sundew.Base.Identification/ValueId.cs Adds ValueId parsing, formatting, and conversion helpers.
Source/Sundew.Base.Identification/TargetEvaluator.cs Resolves source/path metadata into reflection types.
Source/Sundew.Base.Identification/Target.cs Adds target parsing and type-introspection APIs.
Source/Sundew.Base.Identification/Sundew.Base.Identification.csproj Adds the new Identification library project.
Source/Sundew.Base.Identification/Source.cs Adds source formatting/parsing and type resolution.
Source/Sundew.Base.Identification/SequenceIdExtensions.cs Adds sequence-id generation and comparison helpers.
Source/Sundew.Base.Identification/SequenceId.cs Stores per-id-type sequence counters.
Source/Sundew.Base.Identification/Segment.cs Adds path segment representation and formatting.
Source/Sundew.Base.Identification/ScalarValue.cs Adds scalar value serialization.
Source/Sundew.Base.Identification/RevisionId.cs Adds a revision sequence-id type.
Source/Sundew.Base.Identification/Properties/AssemblyInfo.cs Exposes internals to the test project.
Source/Sundew.Base.Identification/Path.cs Adds path representation and formatting.
Source/Sundew.Base.Identification/Parsing/Tokens.cs Defines lexer tokens for ID parsing.
Source/Sundew.Base.Identification/Parsing/IdRouteParser.cs Implements parsing for ids, routes, arguments, and values.
Source/Sundew.Base.Identification/Parsing/IParserError.cs Defines parser error unions for Identification parsing.
Source/Sundew.Base.Identification/Parsing/Grammar.cs Defines the Identification grammar separators/tokens.
Source/Sundew.Base.Identification/LiteralValue.cs Adds literal value serialization.
Source/Sundew.Base.Identification/InstanceId.cs Adds an instance sequence-id type.
Source/Sundew.Base.Identification/IdRoute.cs Adds route parsing for chained ids.
Source/Sundew.Base.Identification/Id.cs Adds the main ID representation, formatting, and expression helpers.
Source/Sundew.Base.Identification/IValueIdentifiable.cs Defines value-identifiable contract.
Source/Sundew.Base.Identification/IValue.cs Defines the value union contract.
Source/Sundew.Base.Identification/ISequenceId.cs Defines sequence-id contract.
Source/Sundew.Base.Identification/IIdentifiable.cs Defines generic identifiable contract.
Source/Sundew.Base.Identification/ExpressionEvaluator.cs Converts expressions into sources, paths, and arguments.
Source/Sundew.Base.Identification/ComplexValue.cs Adds complex/named value serialization.
Source/Sundew.Base.Identification/ArrayValue.cs Adds array value serialization.
Source/Sundew.Base.Identification/Arguments.cs Adds argument collection formatting.
Source/Sundew.Base.Identification/Argument.cs Adds named argument formatting.
Source/Sundew.Base.Identification/AppendOptions.cs Adds append configuration for value formatting.
Source/Sundew.Base.Development.Tests/Threading/ManualResetEventAsyncTests.cs Adjusts one async wait test.
Source/Sundew.Base.Development.Tests/Sundew.Base.Development.Tests.csproj Adds Identification reference and coverlet settings to tests.
Source/Sundew.Base.Development.Tests/Migrations/System_Text_Json/MigrationTests.cs Updates migration test records to partial.
Source/Sundew.Base.Development.Tests/Migrations/System_Text_Json/DeserializationTests.cs Updates deserialization test record to partial.
Source/Sundew.Base.Development.Tests/Migrations/MigrationCancellationTests.cs Updates cancellation test records to partial.
Source/Sundew.Base.Development.Tests/Migrations/DiscriminatedUnionMigrationsTests.cs Updates migration union test records to partial.
Source/Sundew.Base.Development.Tests/Identification/RevisionIdTests.cs Adds tests for sequence-id increment/overflow behavior.
Source/Sundew.Base.Development.Tests/Identification/IdTests.cs Adds broad tests for ID formatting, parsing, and type inspection.
Source/Sundew.Base.Development.Tests/Collections/ValueListTests.cs Adds equality coverage for default vs empty value lists.
Source/Sundew.Base.Development.Tests/Collections/ValueDictionaryTests.cs Adds equality coverage for default vs empty value dictionaries.
Source/Sundew.Base.Development.Tests/Collections/ValueArrayTests.cs Adds equality coverage for default vs empty value arrays.
Source/Sundew.Base.Collections.Linq/Single.cs Marks Single<T> as partial.
Source/Sundew.Base.Collections.Linq/Multiple.cs Marks Multiple<T> as partial.
Source/Sundew.Base.Collections.Linq/Item.cs Adds result-to-item helpers for collection pipelines.
Source/Sundew.Base.Collections.Linq/Empty.cs Marks Empty<T> as partial.
Source/Sundew.Base.Collections.Immutable/ValueList{TItem}.cs Changes equality to treat default and empty lists as equal.
Source/Sundew.Base.Collections.Immutable/ValueDictionary{TKey,TValue}.cs Changes equality to treat default and empty dictionaries as equal.
Source/Sundew.Base.Collections.Immutable/ValueArray{TItem}.cs Changes equality to treat default and empty arrays as equal.
Source/Directory.Packages.props Updates central package versions.
Source/Directory.Build.targets Suppresses TFM support warnings for older target frameworks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 199 to +203
public bool Equals(ValueDictionary<TKey, TValue> other)
{
if (this.Count == 0 && other.Count == 0)
{
return true;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already fixed in d6ac42dGetHashCode() for ValueDictionary now returns 0 when Count == 0, consistent with the equality rule.

Comment on lines 176 to +180
public bool Equals(ValueArray<TItem> other)
{
if (this.Count == 0 && other.Count == 0)
{
return true;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already fixed in d6ac42dGetHashCode() for ValueArray now returns 0 when Count == 0, consistent with the equality rule.

return new R<(TSuccess1, TSuccess2, TSuccess3, TSuccess4), TError>(false, default, otherResult.Error);
}

return new R<(TSuccess1, TSuccess2, TSuccess3, TSuccess4), TError>(true, default, result.Error);
Comment on lines +39 to +40
var match = regex.Match(input, state.Position);
if (match.Success)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c4f8bc9. Added match.Index == state.Position to the success check, so matches that start after the current position are rejected instead of being accepted.

Comment on lines +170 to +173
var argument = complexValue.Items.FirstOrDefault(x => x.Name == referenceName);
if (argument.HasValue)
{
return TValue.Parse(argument.ValueId.Value.ToString() ?? string.Empty, formatProvider);
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in cee067e. GetScalar now pattern-matches on ScalarValue to access its raw Value string directly instead of calling .ToString() (which applies Uri.EscapeDataString). This ensures strings with reserved characters round-trip correctly through TValue.Parse.

Comment on lines 159 to +163
public bool Equals(ValueList<TItem> other)
{
if (this.Count == 0 && other.Count == 0)
{
return true;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d6ac42d. Updated GetHashCode() in all three types (ValueList, ValueArray, ValueDictionary) to return 0 when Count == 0, consistent with the equality rule that treats default and Empty as equal. Equal instances now always produce the same hash code.

Comment on lines +282 to +285
public bool Undo()
{
return this.stateStack.TryPop(out var _);
}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 030e9c9. Undo() now checks stateStack.Count > 1 before popping, so the initial state (pushed in the constructor) is never removed. Calling Undo() when there is nothing to roll back now safely returns false and leaves the stack intact.

Comment on lines +157 to +168
string? fragment = null;
if (parser.TryAccept(Grammar.LiteralSeparator))
{
var valueIdsResult = Arguments(parser);
if (valueIdsResult.IsSuccess)
{
arguments = valueIdsResult.Value;
}
else
{
return R.Error(IIdError._IdValueIdError(valueIdsResult.Error));
}
Comment on lines +79 to +81
if (arguments.HasValue)
{
return arguments.Items.Select(x => x.ValueId.TryGetType()).AllOrFailed(x => x.ToItem()).Map(x => (IReadOnlyList<Type>)x.Items);
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 030e9c9. GetInputTypes now first attempts metadata-based type resolution for all arguments. When that fails (e.g. primitive/default arguments that omit metadata), it falls back to looking up the method's parameter types from the member signature — using per-argument metadata where available and the declared parameter type as the fallback for each argument individually.

…y when Count == 0

Equal instances (default and Empty) now always return the same hash code (0) when Count == 0, fixing the Equals/GetHashCode contract violation that broke hash-based collections.

Agent-Logs-Url: https://github.com/sundews/Sundew.Base/sessions/d77bd4d4-f942-4427-be6b-c50f0d860b48

Co-authored-by: hugener <5023998+hugener@users.noreply.github.com>
hugener and others added 3 commits May 2, 2026 19:42
… to fall back to member signature for primitive arguments

- Parser.Undo(): now returns false and leaves stack intact when only the initial state remains, preventing InvalidOperationException on subsequent Peek() calls
- TargetEvaluator.GetInputTypes(): when argument metadata-based type resolution fails (e.g. for primitives without metadata), falls back to the target method's parameter types from the member signature

Agent-Logs-Url: https://github.com/sundews/Sundew.Base/sessions/4ed14592-e3bd-41bb-ad4d-b9f6fcdf2e89

Co-authored-by: hugener <5023998+hugener@users.noreply.github.com>
Copilot AI and others added 2 commits May 2, 2026 17:54
ScalarValue.ToString() returns Uri.EscapeDataString output (wire format).
Using it in TValue.Parse() caused round-trip failures for strings with
reserved characters. Now pattern-matching on ScalarValue to access the
raw Value property directly.

Agent-Logs-Url: https://github.com/sundews/Sundew.Base/sessions/5cbb2907-948b-43e1-8b28-653475331fdb

Co-authored-by: hugener <5023998+hugener@users.noreply.github.com>
Copilot AI and others added 2 commits May 2, 2026 18:09
…sition

Regex.Match(input, startat) can return a match starting after startat.
Added match.Index == state.Position check to ensure only matches at the
exact current position are accepted.

Agent-Logs-Url: https://github.com/sundews/Sundew.Base/sessions/28a3fb6e-d0d3-4a43-a06b-da8e4615a660

Co-authored-by: hugener <5023998+hugener@users.noreply.github.com>
…le-item case

- Fix array parsing loop: use IsNext(ArrayEnd) instead of IsNext(GroupStart)
  so [Blue,Green] style arrays correctly terminate at ']'
- Fix IdRoute do-while loop: use TryAccept(IdSeparator) without negation so
  a single-id route with no trailing '>' exits cleanly at end-of-input
- Fix ValueIdBuilder.Build() Single case: wrap in ComplexValue with metadata
  instead of returning single.Item.ValueId bare, preserving round-trip identity

Agent-Logs-Url: https://github.com/sundews/Sundew.Base/sessions/605f58c5-a131-42fb-af81-b359b3a1aa79

Co-authored-by: hugener <5023998+hugener@users.noreply.github.com>
Copilot finished work on behalf of hugener May 2, 2026 18:19
@hugener hugener merged commit 21d486e into main May 2, 2026
1 of 2 checks passed
@hugener hugener deleted the feature/Identification branch May 2, 2026 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants