diff --git a/.editorconfig b/.editorconfig
index 6236ee8..ffccaa5 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,65 +10,40 @@ trim_trailing_whitespace = true
[*.{yml,props,targets,csproj}]
indent_size = 2
+[*.cs]
# IDE0079: Remove unnecessary suppression
dotnet_remove_unnecessary_suppression_exclusions = category:ReSharper
-# IDE0079: Remove unnecessary suppression
-# dotnet_diagnostic.IDE0079.severity = none
-
-# CA2255: The 'ModuleInitializer' attribute should not be used in libraries
-dotnet_diagnostic.CA2255.severity = none
-
-# CS8600: Converting null literal or possible null value to non-nullable type.
-dotnet_diagnostic.CS8600.severity = error
-
-# CS8601: Possible null reference assignment.
-dotnet_diagnostic.CS8601.severity = error
-
-# CS8602: Dereference of a possibly null reference.
-dotnet_diagnostic.CS8602.severity = error
-
-# CS8603: Possible null reference return.
-dotnet_diagnostic.CS8603.severity = error
-
-# CS8604: Possible null reference argument.
-dotnet_diagnostic.CS8604.severity = error
-
-# CS8610: Nullability of reference types in type of parameter doesn't match overridden member.
-dotnet_diagnostic.CS8610.severity = error
-
-# CS8613: Nullability of reference types in return type doesn't match implicitly implemented member.
-dotnet_diagnostic.CS8613.severity = error
-
-# CS8614: Nullability of reference types in type of parameter doesn't match implicitly implemented member.
-dotnet_diagnostic.CS8614.severity = error
-
-# CS8618: Non-nullable field is uninitialized. Consider declaring as nullable.
-dotnet_diagnostic.CS8618.severity = error
-
-# CS8619: Nullability of reference types in value doesn't match target type.
-dotnet_diagnostic.CS8619.severity = error
-
-# CS8620: Argument cannot be used for parameter due to differences in the nullability of reference types.
-dotnet_diagnostic.CS8620.severity = error
-
-# CS8625: Cannot convert null literal to non-nullable reference type.
-dotnet_diagnostic.CS8625.severity = error
-
-# CS8634: The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.
-dotnet_diagnostic.CS8634.severity = error
-
-# CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type.
-dotnet_diagnostic.CS8643.severity = error
-
-# CS8653: A default expression introduces a null value for a type parameter.
-dotnet_diagnostic.CS8653.severity = error
-
-# CS8714: The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'notnull' constraint.
-dotnet_diagnostic.CS8714.severity = error
-
-# IDE0059: Unnecessary assigment of a value
-dotnet_diagnostic.IDE0059.severity = none
-
-# IDE0060: Remove unused parameter
-dotnet_diagnostic.IDE0060.severity = none
+[tests/**.cs]
+# CA1707: Identifiers should not contain underscores
+# Tests follow the Method_Condition_ExpectedResult naming convention.
+dotnet_diagnostic.CA1707.severity = none
+
+# CA1304, CA1305, CA1311: culture-sensitive calls
+# Tests cover all StringComparison values and change the current culture on purpose.
+dotnet_diagnostic.CA1304.severity = none
+dotnet_diagnostic.CA1305.severity = none
+dotnet_diagnostic.CA1311.severity = none
+
+# CA1861: Avoid constant arrays as arguments
+# CA1866: Use char overload
+# Test inputs are built per test case; the performance of test code is irrelevant.
+dotnet_diagnostic.CA1861.severity = none
+dotnet_diagnostic.CA1866.severity = none
+
+[benchmarks/**.cs]
+# CA1707: Identifiers should not contain underscores
+# Underscores keep the generated BenchmarkDotNet report readable.
+dotnet_diagnostic.CA1707.severity = none
+
+# CA1822: Mark members as static
+# BenchmarkDotNet discovers instance methods and properties.
+dotnet_diagnostic.CA1822.severity = none
+
+# CA2201: Do not raise reserved exception types
+# Benchmark setup throws Exception to abort a run on an unexpected parser result.
+dotnet_diagnostic.CA2201.severity = none
+
+# CA1806: Do not ignore method results
+# Benchmarks intentionally ignore TryParse results.
+dotnet_diagnostic.CA1806.severity = none
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index d0da5db..b6f6990 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -19,7 +19,7 @@ jobs:
- name: Install .NET
uses: actions/setup-dotnet@v4
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Checkout
uses: actions/checkout@v4
diff --git a/Directory.Build.props b/Directory.Build.props
index ed14ea7..9e6caca 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,4 +2,18 @@
true
+
+
+ $(NoWarn);CS0649
+ true
+
+
+
+ true
+ latest
+ Recommended
+ Default
+ true
+ true
+
diff --git a/benchmarks/Parsers/PidginParsers.cs b/benchmarks/Parsers/PidginParsers.cs
index 7e3359e..7b73926 100644
--- a/benchmarks/Parsers/PidginParsers.cs
+++ b/benchmarks/Parsers/PidginParsers.cs
@@ -94,7 +94,7 @@ public static class JsonParser
Char('r').Select (_ => '\r'),
Char('t').Select (_ => '\t'),
Char('u').Then(HexDigit.Repeat(4)
- .Select(h => (char)int.Parse(new string(h.ToArray()), NumberStyles.HexNumber)))
+ .Select(h => (char)int.Parse(new string(h.ToArray()), NumberStyles.HexNumber, CultureInfo.InvariantCulture)))
)
)
).ManyString().Between(Quote)
diff --git a/samples/TinyC/TinyCParser.cs b/samples/TinyC/TinyCParser.cs
index f1731c6..8f53813 100644
--- a/samples/TinyC/TinyCParser.cs
+++ b/samples/TinyC/TinyCParser.cs
@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
using Ramstack.Parsing;
@@ -21,7 +22,7 @@ private static Parser CreateParser()
var number =
Set("0-9")
.OneOrMore()
- .Map(Node (m) => Node.Number(int.Parse(m)))
+ .Map(Node (m) => Node.Number(int.Parse(m, NumberStyles.Integer, CultureInfo.InvariantCulture)))
.As("number");
var variable =
diff --git a/src/Ramstack.Parsing/NumberKind.cs b/src/Ramstack.Parsing/NumberKind.cs
index 8f83838..77ad650 100644
--- a/src/Ramstack.Parsing/NumberKind.cs
+++ b/src/Ramstack.Parsing/NumberKind.cs
@@ -3,6 +3,8 @@ namespace Ramstack.Parsing;
///
/// Specifies the types of numeric string representations.
///
+[SuppressMessage("Naming", "CA1720:Identifier contains type name",
+ Justification = "The members name the numeric kinds, not the corresponding .NET types.")]
public enum NumberKind
{
///
diff --git a/src/Ramstack.Parsing/OptionalValue.cs b/src/Ramstack.Parsing/OptionalValue.cs
index a7b69c0..f0145f9 100644
--- a/src/Ramstack.Parsing/OptionalValue.cs
+++ b/src/Ramstack.Parsing/OptionalValue.cs
@@ -4,6 +4,8 @@ namespace Ramstack.Parsing;
/// Represents an optional value of type .
///
/// The underlying type of the optional value.
+[SuppressMessage("Design", "CA1051:Do not declare visible instance fields",
+ Justification = "For performance reasons, the field is read in place, while a property getter would copy large T values on every access.")]
public readonly struct OptionalValue
{
///
diff --git a/src/Ramstack.Parsing/Parser.Optional.cs b/src/Ramstack.Parsing/Parser.Optional.cs
index 66b0409..6d8d316 100644
--- a/src/Ramstack.Parsing/Parser.Optional.cs
+++ b/src/Ramstack.Parsing/Parser.Optional.cs
@@ -37,15 +37,18 @@ private sealed class OptionalParser(Parser parser) : Parser
public override bool TryParse(ref ParseContext context, out OptionalValue value)
{
- value = default;
-
if (parser.TryParse(ref context, out var result))
{
+ Unsafe.SkipInit(out value);
+
+ // Write directly into the caller's slot: constructing OptionalValue here
+ // would copy T into a temporary and then into `value`.
Unsafe.AsRef(in value.Value) = result;
Unsafe.AsRef(in value.HasValue) = true;
}
else
{
+ value = default;
context.Advance(0);
}
diff --git a/src/Ramstack.Parsing/PositionBookmark.cs b/src/Ramstack.Parsing/PositionBookmark.cs
index 7b3d55f..ac67542 100644
--- a/src/Ramstack.Parsing/PositionBookmark.cs
+++ b/src/Ramstack.Parsing/PositionBookmark.cs
@@ -9,7 +9,7 @@ public readonly struct PositionBookmark
///
/// Gets the zero-based parsing position.
///
- public readonly int Position;
+ public int Position { get; }
///
/// Initializes a new instance of the structure.
diff --git a/src/Ramstack.Parsing/Ramstack.Parsing.csproj b/src/Ramstack.Parsing/Ramstack.Parsing.csproj
index 3be5e70..51957c6 100644
--- a/src/Ramstack.Parsing/Ramstack.Parsing.csproj
+++ b/src/Ramstack.Parsing/Ramstack.Parsing.csproj
@@ -10,11 +10,6 @@
true
-
- 649;1591
- CS8600;CS8601;CS8602;CS8603;CS8604;CS8610;CS8613;CS8614;CS8618;CS8619;CS8620;CS8625;CS8643;CS8653;CS8714
-
-
https://github.com/rameel/ramstack.parsing
Rameel
diff --git a/src/Ramstack.Parsing/Utilities/CharClassExtensions.cs b/src/Ramstack.Parsing/Utilities/CharClassExtensions.cs
index 3b1b20d..3542781 100644
--- a/src/Ramstack.Parsing/Utilities/CharClassExtensions.cs
+++ b/src/Ramstack.Parsing/Utilities/CharClassExtensions.cs
@@ -335,7 +335,7 @@ _ when controls.Contains(c) => "\\" + c,
else
{
sb.Append("\\u");
- sb.Append(((ushort)c).ToString("x4"));
+ sb.Append(((ushort)c).ToString("x4", provider: null));
}
}