Skip to content

Commit b51ac46

Browse files
Merge pull request #26 from TimeWarpEngineering/Cramer/2025-07-31/filename-rule
Fix indexer generation and add documentation for interface delegation
2 parents 1a6838e + f758b43 commit b51ac46

File tree

5 files changed

+118
-5
lines changed

5 files changed

+118
-5
lines changed

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<ItemGroup>
3-
<PackageVersion Include="TimeWarp.SourceGenerators" Version="$(Version)" />
3+
<PackageVersion Include="TimeWarp.SourceGenerators" Version="1.0.0-beta.6" />
44
<PackageVersion Include="FakeItEasy" Version="7.3.1" />
55
<PackageVersion Include="Fixie" Version="3.2.0" />
66
<PackageVersion Include="Fixie.TestAdapter" Version="3.3.0" />

readme.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,65 @@ TimeWarp.SourceGenerators is our collection of source generators.
2222

2323
If you like or are using this project please give it a star. Thank you!
2424

25+
## Features
26+
27+
### Interface Delegation Generator
28+
29+
Implements Delphi-style interface delegation for C#. Mark fields or properties with `[Implements]` to automatically generate forwarding methods for interface members.
30+
31+
#### Usage
32+
33+
```csharp
34+
public partial class DataService : ILogger, IDataProcessor<string>
35+
{
36+
[Implements]
37+
private readonly ILogger Logger;
38+
39+
[Implements]
40+
private readonly IDataProcessor<string> Processor;
41+
42+
public DataService(ILogger logger, IDataProcessor<string> processor)
43+
{
44+
Logger = logger;
45+
Processor = processor;
46+
}
47+
48+
// Optionally override specific methods
49+
public string Process(string input)
50+
{
51+
// Custom implementation
52+
return Processor.Process(input.ToUpper());
53+
}
54+
}
55+
```
56+
57+
The generator will automatically create forwarding implementations for all interface methods and properties, except those you explicitly implement.
58+
59+
#### Requirements
60+
61+
- Class must be marked as `partial`
62+
- Class must implement the interface being delegated
63+
- Field/property type must be the interface or implement the interface
64+
65+
#### Diagnostics
66+
67+
- **TW1001**: Class must be partial for interface delegation
68+
- **TW1002**: Class does not implement the delegated interface
69+
- **TW1003**: Multiple fields delegate the same interface
70+
71+
### File Name Rule Analyzer
72+
73+
Enforces kebab-case naming convention for C# files.
74+
75+
#### Configuration
76+
77+
Configure exceptions in `.editorconfig`:
78+
79+
```ini
80+
[*.cs]
81+
dotnet_diagnostic.TWA001.excluded_files = Program.cs;Startup.cs;*.Designer.cs
82+
```
83+
2584
## Getting started
2685

2786
To quickly get started I recommend reviewing the samples in this repo.

source/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<!-- Default package metadata (can be overridden in individual projects) -->
66
<PropertyGroup Label="Package Metadata">
7-
<Version>1.0.0-beta.5</Version>
7+
<Version>1.0.0-beta.6</Version>
88
<Authors>Steven T. Cramer</Authors>
99
<Product>TimeWarp.SourceGenerators</Product>
1010
<PackageId>TimeWarp.SourceGenerators</PackageId>

source/timewarp-source-generators/interface-delegation-generator.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,13 +320,30 @@ private static string GeneratePropertyDelegation(IPropertySymbol property, strin
320320
string propertyType = property.Type.ToDisplayString();
321321
string propertyName = property.Name;
322322

323-
string getter = property.GetMethod != null ? $" get => {delegateMemberName}.{propertyName};" : "";
324-
string setter = property.SetMethod != null ? $" set => {delegateMemberName}.{propertyName} = value;" : "";
323+
// Check if this is an indexer
324+
if (property.IsIndexer)
325+
{
326+
string parameters = string.Join(", ", property.Parameters.Select(p =>
327+
$"{p.Type.ToDisplayString()} {p.Name}"));
328+
string arguments = string.Join(", ", property.Parameters.Select(p => p.Name));
325329

326-
return $@" public {propertyType} {propertyName}
330+
string getter = property.GetMethod != null ? $" get => {delegateMemberName}[{arguments}];" : "";
331+
string setter = property.SetMethod != null ? $" set => {delegateMemberName}[{arguments}] = value;" : "";
332+
333+
return $@" public {propertyType} this[{parameters}]
327334
{{
328335
{getter}{setter}
329336
}}";
337+
}
338+
339+
// Regular property
340+
string regularGetter = property.GetMethod != null ? $" get => {delegateMemberName}.{propertyName};" : "";
341+
string regularSetter = property.SetMethod != null ? $" set => {delegateMemberName}.{propertyName} = value;" : "";
342+
343+
return $@" public {propertyType} {propertyName}
344+
{{
345+
{regularGetter}{regularSetter}
346+
}}";
330347
}
331348

332349
private static string GenerateEventDelegation(IEventSymbol eventSymbol, string delegateMemberName)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// <auto-generated/>
2+
#nullable enable
3+
4+
namespace TimeWarp.SourceGenerators.TestConsole;
5+
6+
// Interface delegation for DataService
7+
public partial class DataService
8+
{
9+
// Delegation to _logger for TimeWarp.SourceGenerators.TestConsole.ILogger
10+
public void Log(string message)
11+
{
12+
_logger.Log(message);
13+
}
14+
15+
public void LogError(string message, System.Exception exception)
16+
{
17+
_logger.LogError(message, exception);
18+
}
19+
20+
public TimeWarp.SourceGenerators.TestConsole.LogLevel MinimumLevel
21+
{
22+
get => _logger.MinimumLevel; set => _logger.MinimumLevel = value;
23+
}
24+
25+
public event System.EventHandler<TimeWarp.SourceGenerators.TestConsole.LogEventArgs>? LogWritten
26+
{
27+
add => _logger.LogWritten += value;
28+
remove => _logger.LogWritten -= value;
29+
}
30+
31+
// Delegation to _processor for TimeWarp.SourceGenerators.TestConsole.IDataProcessor<string>
32+
public bool Validate(string input)
33+
{
34+
return _processor.Validate(input);
35+
}
36+
37+
}

0 commit comments

Comments
 (0)