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
8 changes: 1 addition & 7 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ file_header_template = unset

# this. and Me. preferences
dotnet_style_qualification_for_event = false:warning
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_field = true:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_property = false:warning

Expand Down Expand Up @@ -231,8 +231,6 @@ csharp_preserve_single_line_statements = false
# Styles
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
dotnet_naming_style.camel_case_style.capitalization = camel_case
dotnet_naming_style.underscore_prefix_style.capitalization = camel_case
dotnet_naming_style.underscore_prefix_style.required_prefix = _

# Symbols
dotnet_naming_symbols.all_types.applicable_kinds = class, struct, enum, interface, record
Expand Down Expand Up @@ -265,10 +263,6 @@ dotnet_naming_rule.public_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.public_members_should_be_pascal_case.symbols = public_members
dotnet_naming_rule.public_members_should_be_pascal_case.style = pascal_case_style

dotnet_naming_rule.private_fields_should_have_underscore_prefix.severity = suggestion
dotnet_naming_rule.private_fields_should_have_underscore_prefix.symbols = private_fields
dotnet_naming_rule.private_fields_should_have_underscore_prefix.style = underscore_prefix_style

############################################################
# Disabled rules
############################################################
Expand Down
26 changes: 24 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,29 @@
- Use documentation comments with summaries and parameter descriptions.
- Use consistent naming rules for interfaces, type parameters, and fields.
- Use static local functions and simplified `new` expressions.
- Make only high confidence suggestions when reviewing code changes.
- Write code with good maintainability practices, including comments on why certain design decisions were made.
- Handle edge cases and write clear exception handling.
- For libraries or external dependencies, mention their usage and purpose in comments.
- Insert a newline before the opening curly brace of any code block (e.g., after `if`, `for`, `while`, `foreach`, `using`, `try`, etc.).
- Ensure that the final return statement of a method is on its own line.
- Use pattern matching and switch expressions wherever possible.
- Use `nameof` instead of string literals when referring to member names.
- Ensure that XML doc comments are created for any public APIs. When applicable, include `<example>` and `<code>` documentation in the comments.

---

## C# Instructions
- Always use the latest version C#, currently C# 14 features.
- Write clear and concise comments for each function.


## C# Style Preferences
- Apply code-formatting style defined in `.editorconfig`.
- Never add more than one class/interface/enum/struct per file.
- Use PascalCase for public constants and static readonly fields.
- Use camelCase with and underscore prefix for private fields and local variables.
- Use camelCase for private fields and local variables.
- Use camelCase for private readonly fields.
- Prefix interfaces with `I` and type parameters with `T`.
- Use explicit types for built-in types (`string`, `int`, `bool`, etc.)
- Use `var` for complex types when the type is obvious from the right side
Expand All @@ -54,7 +70,7 @@
- Prefer `nameof` over `typeof` where applicable.
- Use tuple swap syntax for swapping values.
- Use static local functions where possible.
- Add an empty line before `return`, `throw`, `break`, `yield`, and `continue`, when it's not the only line. If the previous line is a comment, the empty line should be added before the comment.
- Add an empty line before `return`, `throw`, `break`, `yield`, and `continue`, when it's not the only line in a block. If the previous line is a comment and there's a code line before it, the empty line should be added before the comment.
- Place a blank line between method declarations.
- Avoid multiple statements on a single line.
- Align parameters and arguments vertically with one level of indentation.
Expand All @@ -65,6 +81,12 @@
- Don't add unnecessary using statements.
- Always add an empty line between lines of code and statement blocks.

### Nullable Reference Types

- Declare variables non-nullable, and check for `null` at entry points.
- Always use `is null` or `is not null` instead of `== null` or `!= null`.
- Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.

### Documentation Preferences
- Use XML documentation comments for public members.
- Keep the XML documentation comment lines length under 100 characters.
Expand Down
6 changes: 3 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
<LangVersion>14</LangVersion>
<RootNamespace>$(MSBuildProjectName.Replace(" ", "_"))</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down Expand Up @@ -30,8 +30,8 @@
package source defined in your configuration. We don't get this warning because we're
using source mapping, but we still disable it just to play it safe.
-->
<!-- <GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn),1573,1591,1712,NU1507</NoWarn> -->
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn),1573,1591,1712,NU1507</NoWarn>
</PropertyGroup>

<!-- DefaultDocumentation settings => https://github.com/Doraku/DefaultDocumentation -->
Expand Down
21 changes: 11 additions & 10 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,30 @@
<ItemGroup>
<PackageVersion Include="AutoFixture" Version="4.18.1" />
<PackageVersion Include="AutoFixture.AutoNSubstitute" Version="4.18.1" />
<PackageVersion Include="AwesomeAssertions" Version="9.2.0" />
<PackageVersion Include="AwesomeAssertions" Version="9.2.1" />
<PackageVersion Include="AwesomeAssertions.Analyzers" Version="9.0.3" />
<PackageVersion Include="BenchmarkDotNet" Version="0.15.4" />
<PackageVersion Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="9.9.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.9" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.9" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.9" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.9" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.9" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="9.10.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.10" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageVersion Include="Microsoft.VisualStudio.DiagnosticsHub.BenchmarkDotNetDiagnosers" Version="18.0.36421.1" />
<PackageVersion Include="MSTest" Version="3.11.0" />
<PackageVersion Include="MSTest.Analyzers" Version="3.11.0" />
<PackageVersion Include="MSTest" Version="4.0.1" />
<PackageVersion Include="MSTest.Analyzers" Version="4.0.1" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
<PackageVersion Include="System.Threading.RateLimiting" Version="9.0.10" />
</ItemGroup>
<!-- Transitive packages. Versions are specified to avoid vulnerabilities -->
<ItemGroup>
Expand All @@ -65,4 +66,4 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
</Project>
3 changes: 3 additions & 0 deletions docs/api/DevElf.Benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#### [DevElf\.Benchmarks](README.md 'README')

## DevElf\.Benchmarks Assembly
14 changes: 14 additions & 0 deletions docs/api/DevElf.Logging/DevElf.Logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#### [DevElf\.Logging](README.md 'README')

## DevElf\.Logging Namespace

| Classes | |
| :--- | :--- |
| [LoggerExtensions](LoggerExtensions.md 'DevElf\.Logging\.LoggerExtensions') | Extension methods for [Microsoft\.Extensions\.Logging\.ILogger](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger 'Microsoft\.Extensions\.Logging\.ILogger') to integrate with [DevElf\.Logging\.LogMessageScope](https://learn.microsoft.com/en-us/dotnet/api/develf.logging.logmessagescope 'DevElf\.Logging\.LogMessageScope')\. |
| [LogMessageScopeAccessor](LogMessageScopeAccessor.md 'DevElf\.Logging\.LogMessageScopeAccessor') | Provides access to the current [log message scope](https://learn.microsoft.com/en-us/dotnet/api/develf.logging.logmessagescope 'DevElf\.Logging\.LogMessageScope')\. |
| [ServiceCollectionExtensions](ServiceCollectionExtensions.md 'DevElf\.Logging\.ServiceCollectionExtensions') | Extension methods for configuring log message scope services in dependency injection\. |

| Interfaces | |
| :--- | :--- |
| [ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope') | Represents an ambient log message scope\. Implementations buffer properties and emit a log entry on [System\.IDisposable\.Dispose](https://learn.microsoft.com/en-us/dotnet/api/system.idisposable.dispose 'System\.IDisposable\.Dispose')\. |
| [ILogMessageScopeAccessor](ILogMessageScopeAccessor.md 'DevElf\.Logging\.ILogMessageScopeAccessor') | Provides access to the current [ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope')\. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#### [DevElf\.Logging](README.md 'README')
### [DevElf\.Logging](DevElf.Logging.md 'DevElf\.Logging').[ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope')

## ILogMessageScope\.ChangeEventId\(EventId\) Method

Changes the [Microsoft\.Extensions\.Logging\.EventId](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.eventid 'Microsoft\.Extensions\.Logging\.EventId') that will be used when this scope emits its log entry on dispose\.

```csharp
void ChangeEventId(Microsoft.Extensions.Logging.EventId eventId);
```
#### Parameters

<a name='DevElf.Logging.ILogMessageScope.ChangeEventId(Microsoft.Extensions.Logging.EventId).eventId'></a>

`eventId` [Microsoft\.Extensions\.Logging\.EventId](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.eventid 'Microsoft\.Extensions\.Logging\.EventId')

The new event identifier\.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#### [DevElf\.Logging](README.md 'README')
### [DevElf\.Logging](DevElf.Logging.md 'DevElf\.Logging').[ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope')

## ILogMessageScope\.ChangeLogLevel\(LogLevel\) Method

Changes the log level that will be used when this scope emits its log entry on dispose\.

```csharp
void ChangeLogLevel(Microsoft.Extensions.Logging.LogLevel logLevel);
```
#### Parameters

<a name='DevElf.Logging.ILogMessageScope.ChangeLogLevel(Microsoft.Extensions.Logging.LogLevel).logLevel'></a>

`logLevel` [Microsoft\.Extensions\.Logging\.LogLevel](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.loglevel 'Microsoft\.Extensions\.Logging\.LogLevel')

The new log level\.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#### [DevElf\.Logging](README.md 'README')
### [DevElf\.Logging](DevElf.Logging.md 'DevElf\.Logging').[ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope')

## ILogMessageScope\.ChangeMessage\(string\) Method

Changes the message that will be logged when this scope is disposed\.

```csharp
void ChangeMessage(string message);
```
#### Parameters

<a name='DevElf.Logging.ILogMessageScope.ChangeMessage(string).message'></a>

`message` [System\.String](https://learn.microsoft.com/en-us/dotnet/api/system.string 'System\.String')

The new message\. Cannot be [null](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/null 'https://docs\.microsoft\.com/en\-us/dotnet/csharp/language\-reference/keywords/null'), empty, or whitespace\.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#### [DevElf\.Logging](README.md 'README')
### [DevElf\.Logging](DevElf.Logging.md 'DevElf\.Logging').[ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope')

## ILogMessageScope\.SetException\(Exception, bool\) Method

Sets an [System\.Exception](https://learn.microsoft.com/en-us/dotnet/api/system.exception 'System\.Exception') on the scope and also adds it as a scope property under the key "Exception"\.

```csharp
void SetException(System.Exception exception, bool setAsProperty=true);
```
#### Parameters

<a name='DevElf.Logging.ILogMessageScope.SetException(System.Exception,bool).exception'></a>

`exception` [System\.Exception](https://learn.microsoft.com/en-us/dotnet/api/system.exception 'System\.Exception')

The exception to associate with the log entry\.

<a name='DevElf.Logging.ILogMessageScope.SetException(System.Exception,bool).setAsProperty'></a>

`setAsProperty` [System\.Boolean](https://learn.microsoft.com/en-us/dotnet/api/system.boolean 'System\.Boolean')

If [true](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/bool 'https://docs\.microsoft\.com/en\-us/dotnet/csharp/language\-reference/builtin\-types/bool'), also sets the exception as a property under the key "Exception"\.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#### [DevElf\.Logging](README.md 'README')
### [DevElf\.Logging](DevElf.Logging.md 'DevElf\.Logging').[ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope')

## ILogMessageScope\.SetProperty\<T\>\(string, T\) Method

Sets a property on the current scope\.
When multiple scopes are nested, child properties override parent properties with the same key\.

```csharp
T SetProperty<T>(string key, T value);
```
#### Type parameters

<a name='DevElf.Logging.ILogMessageScope.SetProperty_T_(string,T).T'></a>

`T`

The value type\.
#### Parameters

<a name='DevElf.Logging.ILogMessageScope.SetProperty_T_(string,T).key'></a>

`key` [System\.String](https://learn.microsoft.com/en-us/dotnet/api/system.string 'System\.String')

The property key\. Cannot be [null](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/null 'https://docs\.microsoft\.com/en\-us/dotnet/csharp/language\-reference/keywords/null'), empty, or whitespace\.

<a name='DevElf.Logging.ILogMessageScope.SetProperty_T_(string,T).value'></a>

`value` [T](ILogMessageScope.SetProperty.W33WIH8SSDTY69PIOC9JED2Q2.md#DevElf.Logging.ILogMessageScope.SetProperty_T_(string,T).T 'DevElf\.Logging\.ILogMessageScope\.SetProperty\<T\>\(string, T\)\.T')

The property value\.

#### Returns
[T](ILogMessageScope.SetProperty.W33WIH8SSDTY69PIOC9JED2Q2.md#DevElf.Logging.ILogMessageScope.SetProperty_T_(string,T).T 'DevElf\.Logging\.ILogMessageScope\.SetProperty\<T\>\(string, T\)\.T')
Returns the provided [value](ILogMessageScope.SetProperty.W33WIH8SSDTY69PIOC9JED2Q2.md#DevElf.Logging.ILogMessageScope.SetProperty_T_(string,T).value 'DevElf\.Logging\.ILogMessageScope\.SetProperty\<T\>\(string, T\)\.value') to enable fluent assignment\.
21 changes: 21 additions & 0 deletions docs/api/DevElf.Logging/ILogMessageScope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#### [DevElf\.Logging](README.md 'README')
### [DevElf\.Logging](DevElf.Logging.md 'DevElf\.Logging')

## ILogMessageScope Interface

Represents an ambient log message scope\.
Implementations buffer properties and emit a log entry on [System\.IDisposable\.Dispose](https://learn.microsoft.com/en-us/dotnet/api/system.idisposable.dispose 'System\.IDisposable\.Dispose')\.

```csharp
public interface ILogMessageScope : System.IDisposable
```

Implements [System\.IDisposable](https://learn.microsoft.com/en-us/dotnet/api/system.idisposable 'System\.IDisposable')

| Methods | |
| :--- | :--- |
| [ChangeEventId\(EventId\)](ILogMessageScope.ChangeEventId.2II91DHU6UBPX38ZVB3F7A973.md 'DevElf\.Logging\.ILogMessageScope\.ChangeEventId\(Microsoft\.Extensions\.Logging\.EventId\)') | Changes the [Microsoft\.Extensions\.Logging\.EventId](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.eventid 'Microsoft\.Extensions\.Logging\.EventId') that will be used when this scope emits its log entry on dispose\. |
| [ChangeLogLevel\(LogLevel\)](ILogMessageScope.ChangeLogLevel.T8V2CVT94S8T3JEG5QV4IHR23.md 'DevElf\.Logging\.ILogMessageScope\.ChangeLogLevel\(Microsoft\.Extensions\.Logging\.LogLevel\)') | Changes the log level that will be used when this scope emits its log entry on dispose\. |
| [ChangeMessage\(string\)](ILogMessageScope.ChangeMessage.2FDKFV78GR308BJBSTOALKPQ1.md 'DevElf\.Logging\.ILogMessageScope\.ChangeMessage\(string\)') | Changes the message that will be logged when this scope is disposed\. |
| [SetException\(Exception, bool\)](ILogMessageScope.SetException.RD4VYIJ1SQ9EVWX51XVKJSNO7.md 'DevElf\.Logging\.ILogMessageScope\.SetException\(System\.Exception, bool\)') | Sets an [System\.Exception](https://learn.microsoft.com/en-us/dotnet/api/system.exception 'System\.Exception') on the scope and also adds it as a scope property under the key "Exception"\. |
| [SetProperty&lt;T&gt;\(string, T\)](ILogMessageScope.SetProperty.W33WIH8SSDTY69PIOC9JED2Q2.md 'DevElf\.Logging\.ILogMessageScope\.SetProperty\<T\>\(string, T\)') | Sets a property on the current scope\. When multiple scopes are nested, child properties override parent properties with the same key\. |
14 changes: 14 additions & 0 deletions docs/api/DevElf.Logging/ILogMessageScopeAccessor.Current.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#### [DevElf\.Logging](README.md 'README')
### [DevElf\.Logging](DevElf.Logging.md 'DevElf\.Logging').[ILogMessageScopeAccessor](ILogMessageScopeAccessor.md 'DevElf\.Logging\.ILogMessageScopeAccessor')

## ILogMessageScopeAccessor\.Current Property

Gets the current [ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope'), or
[null](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/null 'https://docs\.microsoft\.com/en\-us/dotnet/csharp/language\-reference/keywords/null') when no scope is active\.

```csharp
DevElf.Logging.ILogMessageScope? Current { get; }
```

#### Property Value
[ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope')
17 changes: 17 additions & 0 deletions docs/api/DevElf.Logging/ILogMessageScopeAccessor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#### [DevElf\.Logging](README.md 'README')
### [DevElf\.Logging](DevElf.Logging.md 'DevElf\.Logging')

## ILogMessageScopeAccessor Interface

Provides access to the current [ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope')\.

```csharp
public interface ILogMessageScopeAccessor
```

Derived
&#8627; [LogMessageScopeAccessor](LogMessageScopeAccessor.md 'DevElf\.Logging\.LogMessageScopeAccessor')

| Properties | |
| :--- | :--- |
| [Current](ILogMessageScopeAccessor.Current.md 'DevElf\.Logging\.ILogMessageScopeAccessor\.Current') | Gets the current [ILogMessageScope](ILogMessageScope.md 'DevElf\.Logging\.ILogMessageScope'), or [null](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/null 'https://docs\.microsoft\.com/en\-us/dotnet/csharp/language\-reference/keywords/null') when no scope is active\. |
Loading