Skip to content
Merged
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
3 changes: 2 additions & 1 deletion .docfx/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
"fileMetadataFiles": [],
"template": [
"default",
"modern"
"modern",
"templates/modern"
],
"overwrite": [
{
Expand Down
12 changes: 12 additions & 0 deletions .docfx/templates/modern/public/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default {
start: () => {
const script = document.createElement('script');
script.src = 'https://context7.com/widget.js';
script.setAttribute('data-library', '/codebeltnet/xunit');
script.setAttribute('data-color', '#059669');
script.setAttribute('data-position', 'bottom-right');
script.setAttribute('data-placeholder', 'Ask about Codebelt.Extensions.Xunit...');
script.async = true;
document.body.appendChild(script);
}
};
187 changes: 187 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

# Default: prefer spaces for data/markup
indent_style = space
indent_size = 2
tab_width = 2

# This style rule concern the use of the range operator, which is available in C# 8.0 and later.
# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0057
[*.{cs,vb}]
dotnet_diagnostic.IDE0057.severity = none

# This style rule concerns the use of switch expressions versus switch statements.
# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0066
[*.{cs,vb}]
dotnet_diagnostic.IDE0066.severity = none

# Performance rules
# https://docs.microsoft.com/da-dk/dotnet/fundamentals/code-analysis/quality-rules/performance-warnings
[*.{cs,vb}]
dotnet_analyzer_diagnostic.category-Performance.severity = none # Because many of the suggestions by performance analyzers are not compatible with .NET Standard 2.0

# This style rule concerns the use of using statements without curly braces, also known as using declarations. This alternative syntax was introduced in C# 8.0.
# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0063
[*.{cs,vb}]
dotnet_diagnostic.IDE0063.severity = none

# This style rule concerns with simplification of interpolated strings to improve code readability. It recommends removal of certain explicit method calls, such as ToString(), when the same method would be implicitly invoked by the compiler if the explicit method call is removed.
# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0071
[*.{cs,vb}]
dotnet_diagnostic.IDE0071.severity = none

# S3267: Loops should be simplified with "LINQ" expressions
# https://rules.sonarsource.com/csharp/RSPEC-3267
dotnet_diagnostic.S3267.severity = none

# CA1859: Use concrete types when possible for improved performance
# This is a violation of Framework Design Guidelines.
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1859
[*.{cs,vb}]
dotnet_diagnostic.CA1859.severity = none

# IDE0008: Use explicit type
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0007-ide0008
[*.{cs,vb}]
dotnet_diagnostic.IDE0008.severity = none

[*.{cs,vb}]
indent_style = space
indent_size = 4

# IDE0161: Namespace declaration preferences
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0161
# Prefer file-scoped namespaces for new files; existing block-scoped files should not be converted unless explicitly asked
[*.cs]
csharp_style_namespace_declarations = file_scoped:suggestion

# Top-level statements: DO NOT USE
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0210-ide0211
# This is enforced via a style preference set to error severity, not a language-level prohibition.
# Always use explicit class declarations with a proper namespace and Main method where applicable.
[*.cs]
csharp_style_prefer_top_level_statements = false:error

[*.xml]
indent_style = space
indent_size = 2

# IDE0078: Use pattern matching
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0078
[*.{cs,vb}]
dotnet_diagnostic.IDE0078.severity = none

# IDE0290: Use primary constructor
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0290
[*.{cs,vb}]
dotnet_diagnostic.IDE0290.severity = none

# CA1200: Avoid using cref tags with a prefix
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1200
[*.{cs,vb}]
dotnet_diagnostic.CA1200.severity = none

# IDE0305: Use collection expression for fluent
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0305
[*.{cs,vb}]
dotnet_diagnostic.IDE0305.severity = none

# IDE0011: Add braces
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0011
[*.{cs,vb}]
dotnet_diagnostic.IDE0011.severity = none

# IDE0028: Use collection initializers or expressions
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0028
[*.{cs,vb}]
dotnet_diagnostic.IDE0028.severity = none

# IDE0039: Use collection expression for array
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0300
[*.{cs,vb}]
dotnet_diagnostic.IDE0300.severity = none
Comment on lines +105 to +108
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading rule IDs in comments — "IDE0039" and "IDE0031" should be "IDE0300" and "IDE0301"

Both comment lines reference old, unrelated rule IDs:

  • Line 105: # IDE0039: Use collection expression for array — IDE0039 is "Use local function"; the suppressed rule and linked URL are for IDE0300.
  • Line 110: # IDE0031: Use collection expression for empty — IDE0031 is "Use null propagation"; the suppressed rule and linked URL are for IDE0301.
📝 Proposed fix
-# IDE0039: Use collection expression for array
-# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0300
+# IDE0300: Use collection expression for array
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0300
 [*.{cs,vb}]
 dotnet_diagnostic.IDE0300.severity = none

-# IDE0031: Use collection expression for empty
-# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0301
+# IDE0301: Use collection expression for empty
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0301
 [*.{cs,vb}]
 dotnet_diagnostic.IDE0301.severity = none

Also applies to: 110-113

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.editorconfig around lines 105 - 108, Update the misleading comment rule IDs
to match the suppressed rules: replace occurrences of "IDE0039" with "IDE0300"
in the comment that precedes the IDE0300 suppression (the block that currently
says "Use collection expression for array") and replace "IDE0031" with "IDE0301"
in the comment that precedes the IDE0301 suppression (the block that currently
says "Use collection expression for empty"); ensure the comment text and IDs
align with the dotnet_diagnostic entries (IDE0300 and IDE0301) so the comments
accurately describe the suppressed rules.


# IDE0031: Use collection expression for empty
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0301
[*.{cs,vb}]
dotnet_diagnostic.IDE0301.severity = none

# IDE0046: Use conditional expression for return
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0046
[*.{cs,vb}]
dotnet_diagnostic.IDE0046.severity = none

# IDE0047: Parentheses preferences
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0047-ide0048
[*.{cs,vb}]
dotnet_diagnostic.IDE0047.severity = none

# CA1716: Identifiers should not match keywords
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1716
[*.{cs,vb}]
dotnet_diagnostic.CA1716.severity = none

# CA1720: Identifiers should not contain type names
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1720
[*.{cs,vb}]
dotnet_diagnostic.CA1720.severity = none

# CA1846: Prefer AsSpan over Substring
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1846
# Excluded while TFMs include netstandard2.0
[*.{cs,vb}]
dotnet_diagnostic.CA1846.severity = none

# CA1847: Use String.Contains(char) instead of String.Contains(string) with single characters
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1847
# Excluded while TFMs include netstandard2.0
[*.{cs,vb}]
dotnet_diagnostic.CA1847.severity = none

# CA1865-CA1867: Use 'string.Method(char)' instead of 'string.Method(string)' for string with single char
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1865-ca1867
# Excluded while TFMs include netstandard2.0
[*.{cs,vb}]
dotnet_diagnostic.CA1865.severity = none
dotnet_diagnostic.CA1866.severity = none
dotnet_diagnostic.CA1867.severity = none

# CA2263: Prefer generic overload when type is known
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2263
# Excluded while TFMs include netstandard2.0
[*.{cs,vb}]
dotnet_diagnostic.CA2263.severity = none

# CA2249: Consider using String.Contains instead of String.IndexOf
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2249
# Excluded while TFMs include netstandard2.0
[*.{cs,vb}]
dotnet_diagnostic.CA2249.severity = none

# IDE0022: Use expression body for methods
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0022
[*.{cs,vb}]
dotnet_diagnostic.IDE0022.severity = none

# IDE0032: Use auto-property
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0032
[*.{cs,vb}]
dotnet_diagnostic.IDE0032.severity = none

# Order modifiers
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0036
# Excluded because of inconsistency with other analyzers
[*.{cs,vb}]
dotnet_diagnostic.IDE0036.severity = none

# Use 'System.Threading.Lock'
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0330
# Excluded while TFMs are less than net9.0
[*.{cs,vb}]
dotnet_diagnostic.IDE0330.severity = none
7 changes: 7 additions & 0 deletions .github/dispatch-targets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
"benchmarkdotnet",
"newtonsoft-json",
"aws-signature-v4",
"unitify",
"yamldotnet"
]
116 changes: 116 additions & 0 deletions .github/scripts/bump-nuget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/usr/bin/env python3
"""
Bumps PackageVersion entries in Directory.Packages.props.
- For packages published by the triggering source repo: uses the known TRIGGER_VERSION.
- For all other packages: queries NuGet API for latest stable version.
- Preserves all XML formatting via regex (no ElementTree rewriting).
"""

import re, os, urllib.request, json, sys
from typing import Dict, List

TRIGGER_SOURCE = os.environ.get("TRIGGER_SOURCE", "")
TRIGGER_VERSION = os.environ.get("TRIGGER_VERSION", "")

# Maps source repo name → NuGet package ID prefixes published by that repo.
# Keep this aligned with what each repo actually publishes.
SOURCE_PACKAGE_MAP: Dict[str, List[str]] = {
"cuemon": [
"Cuemon.",
],
"xunit": [
"Codebelt.Extensions.Xunit",
],
"benchmarkdotnet": [
"Codebelt.Extensions.BenchmarkDotNet",
],
"bootstrapper": [
"Codebelt.Bootstrapper",
],
"newtonsoft-json": [
"Codebelt.Extensions.Newtonsoft.Json",
"Codebelt.Extensions.AspNetCore.Mvc.Formatters.Newtonsoft",
],
"aws-signature-v4": [
"Codebelt.Extensions.AspNetCore.Authentication.AwsSignature",
],
"unitify": [
"Codebelt.Unitify",
],
"yamldotnet": [
"Codebelt.Extensions.YamlDotNet",
"Codebelt.Extensions.AspNetCore.Mvc.Formatters.Text.Yaml",
],
"globalization": [
"Codebelt.Extensions.Globalization",
],
"asp-versioning": [
"Codebelt.Extensions.Asp.Versioning",
],
"swashbuckle-aspnetcore": [
"Codebelt.Extensions.Swashbuckle",
],
"savvyio": [
"Savvyio.",
],
"shared-kernel": [],
}


def nuget_latest(pkg: str) -> str | None:
"""Query NuGet flat container API for the latest stable version."""
try:
url = f"https://api.nuget.org/v3-flatcontainer/{pkg.lower()}/index.json"
with urllib.request.urlopen(url, timeout=15) as r:
versions = json.loads(r.read())["versions"]
stable = [v for v in versions if not re.search(r"-", v)]
return stable[-1] if stable else None
except Exception as e:
print(f" SKIP {pkg}: {e}", file=sys.stderr)
return None


def triggered_version(pkg: str) -> str | None:
"""Return TRIGGER_VERSION if pkg is published by the triggering source repo."""
if not TRIGGER_VERSION or not TRIGGER_SOURCE:
return None
prefixes = SOURCE_PACKAGE_MAP.get(TRIGGER_SOURCE, [])
if any(pkg.startswith(p) for p in prefixes):
return TRIGGER_VERSION
return None


with open("Directory.Packages.props", "r") as f:
content = f.read()

changes = []


def replace_version(m: re.Match) -> str:
pkg = m.group(1)
current = m.group(2)

new_ver = triggered_version(pkg) or nuget_latest(pkg) or current

if new_ver != current:
changes.append(f" {pkg}: {current} → {new_ver}")
return m.group(0).replace(f'Version="{current}"', f'Version="{new_ver}"')


pattern = re.compile(
r'<PackageVersion\b'
r'(?=[^>]*\bInclude="([^"]+)")'
r'(?=[^>]*\bVersion="([^"]+)")'
r'[^>]*>',
re.DOTALL,
)
new_content = pattern.sub(replace_version, content)

if changes:
print(f"Bumped {len(changes)} package(s):")
print("\n".join(changes))
else:
print("All packages already at target versions.")

with open("Directory.Packages.props", "w") as f:
f.write(new_content)
Loading
Loading