Skip to content

Commit fa858eb

Browse files
Copilotdex3r
andauthored
Refactor Generators: extract SourceEmitting namespace, decompose ExecutionRuntime, add 59 tests (#90)
* Initial plan * Extract source emitting code into SourceEmitting namespace and refactor ExecutionRuntime - Create CSharpLiteralFormatter for value/key literal formatting - Create CSharpAccessibilityKeyword for accessibility mapping - Create CSharpTypeKeyword for type kind mapping - Create PartialMethodEmitData record and PartialMethodSourceEmitter - Create DummyImplementationEmitter with data records - Create RoslynSymbolDataMapper to bridge Roslyn types to emitter records - Create GeneratorAssemblyExecutor for shared compile/load logic - Create BodyGenerationDataExtractor for reflection-based data extraction - Refactor GeneratesMethodExecutionRuntime to use new classes - Refactor GeneratesMethodPatternSourceBuilder to delegate to SourceEmitting - Add documentation comments to all internal/public methods Co-authored-by: dex3r <3155725+dex3r@users.noreply.github.com> Agent-Logs-Url: https://github.com/dex3r/EasySourceGenerators/sessions/cb205769-20ee-4e1e-9b44-3ef890163968 * Add unit tests for all extracted SourceEmitting classes - CSharpLiteralFormatterTests: 16 tests for value/key literal formatting - CSharpAccessibilityKeywordTests: 10 tests for From and FromOrEmpty - CSharpTypeKeywordTests: 5 tests for type kind mapping - PartialMethodSourceEmitterTests: 12 tests for partial method source emission - DummyImplementationEmitterTests: 11 tests for dummy implementation generation Co-authored-by: dex3r <3155725+dex3r@users.noreply.github.com> Agent-Logs-Url: https://github.com/dex3r/EasySourceGenerators/sessions/cb205769-20ee-4e1e-9b44-3ef890163968 * Address review: replace fragile StaticModifier with MethodModifiers in DummyMethodData Use consistent MethodModifiers pattern ("partial" / "static partial") in DummyMethodData, matching PartialMethodEmitData approach and eliminating the fragile trailing-space convention. Co-authored-by: dex3r <3155725+dex3r@users.noreply.github.com> Agent-Logs-Url: https://github.com/dex3r/EasySourceGenerators/sessions/cb205769-20ee-4e1e-9b44-3ef890163968 * Address review: split files, extract helpers, rename CSharpAccessibilityKeyword - Move LoadedAssemblyContext into its own file - Extract DiagnosticMessageHelper for testable error-joining - Extract AbstractionsAssemblyResolver from GeneratesMethodExecutionRuntime - Extract DataGeneratorsFactorySetup from GeneratesMethodExecutionRuntime - Merge FromOrEmpty into ToKeyword with defaultToPrivate parameter - Add DiagnosticMessageHelperTests (5 tests) - Update CSharpAccessibilityKeywordTests for renamed API (12 tests) Co-authored-by: dex3r <3155725+dex3r@users.noreply.github.com> Agent-Logs-Url: https://github.com/dex3r/EasySourceGenerators/sessions/7c930db8-e3f7-42d9-98cd-41cf86cdc442 * Fix CSharpAccessibilityKeyword doc to list all defaulting cases Co-authored-by: dex3r <3155725+dex3r@users.noreply.github.com> Agent-Logs-Url: https://github.com/dex3r/EasySourceGenerators/sessions/7c930db8-e3f7-42d9-98cd-41cf86cdc442 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: dex3r <3155725+dex3r@users.noreply.github.com>
1 parent 992c089 commit fa858eb

24 files changed

+1822
-681
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using EasySourceGenerators.Generators.SourceEmitting;
2+
using Microsoft.CodeAnalysis;
3+
4+
namespace EasySourceGenerators.GeneratorTests;
5+
6+
[TestFixture]
7+
public class CSharpAccessibilityKeywordTests
8+
{
9+
// -----------------------------------------------------------------------
10+
// ToKeyword with defaultToPrivate = true (default)
11+
// -----------------------------------------------------------------------
12+
13+
[Test]
14+
public void ToKeyword_Public_ReturnsPublic()
15+
{
16+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.Public);
17+
18+
Assert.That(result, Is.EqualTo("public"));
19+
}
20+
21+
[Test]
22+
public void ToKeyword_Protected_ReturnsProtected()
23+
{
24+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.Protected);
25+
26+
Assert.That(result, Is.EqualTo("protected"));
27+
}
28+
29+
[Test]
30+
public void ToKeyword_Internal_ReturnsInternal()
31+
{
32+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.Internal);
33+
34+
Assert.That(result, Is.EqualTo("internal"));
35+
}
36+
37+
[Test]
38+
public void ToKeyword_ProtectedOrInternal_ReturnsProtectedInternal()
39+
{
40+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.ProtectedOrInternal);
41+
42+
Assert.That(result, Is.EqualTo("protected internal"));
43+
}
44+
45+
[Test]
46+
public void ToKeyword_ProtectedAndInternal_ReturnsPrivateProtected()
47+
{
48+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.ProtectedAndInternal);
49+
50+
Assert.That(result, Is.EqualTo("private protected"));
51+
}
52+
53+
[Test]
54+
public void ToKeyword_Private_ReturnsPrivate()
55+
{
56+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.Private);
57+
58+
Assert.That(result, Is.EqualTo("private"));
59+
}
60+
61+
[Test]
62+
public void ToKeyword_NotApplicable_ReturnsPrivate()
63+
{
64+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.NotApplicable);
65+
66+
Assert.That(result, Is.EqualTo("private"));
67+
}
68+
69+
// -----------------------------------------------------------------------
70+
// ToKeyword with defaultToPrivate = false
71+
// -----------------------------------------------------------------------
72+
73+
[Test]
74+
public void ToKeyword_DefaultToPrivateFalse_Public_ReturnsPublic()
75+
{
76+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.Public, defaultToPrivate: false);
77+
78+
Assert.That(result, Is.EqualTo("public"));
79+
}
80+
81+
[Test]
82+
public void ToKeyword_DefaultToPrivateFalse_Protected_ReturnsProtected()
83+
{
84+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.Protected, defaultToPrivate: false);
85+
86+
Assert.That(result, Is.EqualTo("protected"));
87+
}
88+
89+
[Test]
90+
public void ToKeyword_DefaultToPrivateFalse_Internal_ReturnsInternal()
91+
{
92+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.Internal, defaultToPrivate: false);
93+
94+
Assert.That(result, Is.EqualTo("internal"));
95+
}
96+
97+
[Test]
98+
public void ToKeyword_DefaultToPrivateFalse_Private_ReturnsEmptyString()
99+
{
100+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.Private, defaultToPrivate: false);
101+
102+
Assert.That(result, Is.EqualTo(""));
103+
}
104+
105+
[Test]
106+
public void ToKeyword_DefaultToPrivateFalse_NotApplicable_ReturnsEmptyString()
107+
{
108+
string result = CSharpAccessibilityKeyword.ToKeyword(Accessibility.NotApplicable, defaultToPrivate: false);
109+
110+
Assert.That(result, Is.EqualTo(""));
111+
}
112+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
using EasySourceGenerators.Generators.SourceEmitting;
2+
using Microsoft.CodeAnalysis;
3+
using Microsoft.CodeAnalysis.CSharp;
4+
5+
namespace EasySourceGenerators.GeneratorTests;
6+
7+
[TestFixture]
8+
public class CSharpLiteralFormatterTests
9+
{
10+
// -----------------------------------------------------------------------
11+
// FormatValueAsLiteral
12+
// -----------------------------------------------------------------------
13+
14+
[Test]
15+
public void FormatValueAsLiteral_NullValue_ReturnsDefault()
16+
{
17+
string result = CSharpLiteralFormatter.FormatValueAsLiteral(null, SpecialType.System_String, TypeKind.Class, "string");
18+
19+
Assert.That(result, Is.EqualTo("default"));
20+
}
21+
22+
[Test]
23+
public void FormatValueAsLiteral_StringType_ReturnsQuotedLiteral()
24+
{
25+
string result = CSharpLiteralFormatter.FormatValueAsLiteral("hello", SpecialType.System_String, TypeKind.Class, "string");
26+
27+
Assert.That(result, Is.EqualTo("\"hello\""));
28+
}
29+
30+
[Test]
31+
public void FormatValueAsLiteral_StringWithSpecialCharacters_ReturnsEscapedLiteral()
32+
{
33+
string result = CSharpLiteralFormatter.FormatValueAsLiteral("line1\nline2", SpecialType.System_String, TypeKind.Class, "string");
34+
35+
Assert.That(result, Does.Contain("\\n"));
36+
}
37+
38+
[Test]
39+
public void FormatValueAsLiteral_CharType_ReturnsSingleQuotedLiteral()
40+
{
41+
string result = CSharpLiteralFormatter.FormatValueAsLiteral("A", SpecialType.System_Char, TypeKind.Struct, "char");
42+
43+
Assert.That(result, Is.EqualTo("'A'"));
44+
}
45+
46+
[Test]
47+
public void FormatValueAsLiteral_BooleanTrue_ReturnsLowercase()
48+
{
49+
string result = CSharpLiteralFormatter.FormatValueAsLiteral("True", SpecialType.System_Boolean, TypeKind.Struct, "bool");
50+
51+
Assert.That(result, Is.EqualTo("true"));
52+
}
53+
54+
[Test]
55+
public void FormatValueAsLiteral_BooleanFalse_ReturnsLowercase()
56+
{
57+
string result = CSharpLiteralFormatter.FormatValueAsLiteral("False", SpecialType.System_Boolean, TypeKind.Struct, "bool");
58+
59+
Assert.That(result, Is.EqualTo("false"));
60+
}
61+
62+
[Test]
63+
public void FormatValueAsLiteral_EnumType_ReturnsPrefixedValue()
64+
{
65+
string result = CSharpLiteralFormatter.FormatValueAsLiteral("Red", SpecialType.None, TypeKind.Enum, "MyNamespace.Colors");
66+
67+
Assert.That(result, Is.EqualTo("MyNamespace.Colors.Red"));
68+
}
69+
70+
[Test]
71+
public void FormatValueAsLiteral_IntegerType_ReturnsValueAsIs()
72+
{
73+
string result = CSharpLiteralFormatter.FormatValueAsLiteral("42", SpecialType.System_Int32, TypeKind.Struct, "int");
74+
75+
Assert.That(result, Is.EqualTo("42"));
76+
}
77+
78+
[Test]
79+
public void FormatValueAsLiteral_DecimalType_ReturnsValueAsIs()
80+
{
81+
string result = CSharpLiteralFormatter.FormatValueAsLiteral("3.14", SpecialType.System_Double, TypeKind.Struct, "double");
82+
83+
Assert.That(result, Is.EqualTo("3.14"));
84+
}
85+
86+
// -----------------------------------------------------------------------
87+
// FormatKeyAsLiteral
88+
// -----------------------------------------------------------------------
89+
90+
[Test]
91+
public void FormatKeyAsLiteral_EnumType_ReturnsPrefixedValue()
92+
{
93+
string result = CSharpLiteralFormatter.FormatKeyAsLiteral("Green", TypeKind.Enum, "MyNamespace.Colors");
94+
95+
Assert.That(result, Is.EqualTo("MyNamespace.Colors.Green"));
96+
}
97+
98+
[Test]
99+
public void FormatKeyAsLiteral_BoolTrue_ReturnsTrueLiteral()
100+
{
101+
string result = CSharpLiteralFormatter.FormatKeyAsLiteral(true, TypeKind.Struct, "bool");
102+
103+
Assert.That(result, Is.EqualTo("true"));
104+
}
105+
106+
[Test]
107+
public void FormatKeyAsLiteral_BoolFalse_ReturnsFalseLiteral()
108+
{
109+
string result = CSharpLiteralFormatter.FormatKeyAsLiteral(false, TypeKind.Struct, "bool");
110+
111+
Assert.That(result, Is.EqualTo("false"));
112+
}
113+
114+
[Test]
115+
public void FormatKeyAsLiteral_String_ReturnsQuotedLiteral()
116+
{
117+
string result = CSharpLiteralFormatter.FormatKeyAsLiteral("hello", TypeKind.Class, "string");
118+
119+
Assert.That(result, Is.EqualTo("\"hello\""));
120+
}
121+
122+
[Test]
123+
public void FormatKeyAsLiteral_Integer_ReturnsToStringResult()
124+
{
125+
string result = CSharpLiteralFormatter.FormatKeyAsLiteral(42, TypeKind.Struct, "int");
126+
127+
Assert.That(result, Is.EqualTo("42"));
128+
}
129+
130+
[Test]
131+
public void FormatKeyAsLiteral_NullTypeKind_UsesDefaultBehavior()
132+
{
133+
string result = CSharpLiteralFormatter.FormatKeyAsLiteral(99, null, null);
134+
135+
Assert.That(result, Is.EqualTo("99"));
136+
}
137+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using EasySourceGenerators.Generators.SourceEmitting;
2+
using Microsoft.CodeAnalysis;
3+
4+
namespace EasySourceGenerators.GeneratorTests;
5+
6+
[TestFixture]
7+
public class CSharpTypeKeywordTests
8+
{
9+
[Test]
10+
public void From_Class_ReturnsClass()
11+
{
12+
string result = CSharpTypeKeyword.From(TypeKind.Class);
13+
14+
Assert.That(result, Is.EqualTo("class"));
15+
}
16+
17+
[Test]
18+
public void From_Struct_ReturnsStruct()
19+
{
20+
string result = CSharpTypeKeyword.From(TypeKind.Struct);
21+
22+
Assert.That(result, Is.EqualTo("struct"));
23+
}
24+
25+
[Test]
26+
public void From_Interface_ReturnsInterface()
27+
{
28+
string result = CSharpTypeKeyword.From(TypeKind.Interface);
29+
30+
Assert.That(result, Is.EqualTo("interface"));
31+
}
32+
33+
[Test]
34+
public void From_Enum_ReturnsClass()
35+
{
36+
string result = CSharpTypeKeyword.From(TypeKind.Enum);
37+
38+
Assert.That(result, Is.EqualTo("class"));
39+
}
40+
41+
[Test]
42+
public void From_Delegate_ReturnsClass()
43+
{
44+
string result = CSharpTypeKeyword.From(TypeKind.Delegate);
45+
46+
Assert.That(result, Is.EqualTo("class"));
47+
}
48+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using EasySourceGenerators.Generators.IncrementalGenerators;
2+
using Microsoft.CodeAnalysis;
3+
using Microsoft.CodeAnalysis.CSharp;
4+
5+
namespace EasySourceGenerators.GeneratorTests;
6+
7+
[TestFixture]
8+
public class DiagnosticMessageHelperTests
9+
{
10+
[Test]
11+
public void JoinErrorDiagnostics_EmptyList_ReturnsEmptyString()
12+
{
13+
string result = DiagnosticMessageHelper.JoinErrorDiagnostics(Array.Empty<Diagnostic>());
14+
15+
Assert.That(result, Is.EqualTo(""));
16+
}
17+
18+
[Test]
19+
public void JoinErrorDiagnostics_OnlyWarnings_ReturnsEmptyString()
20+
{
21+
Diagnostic[] diagnostics = new[]
22+
{
23+
CreateDiagnostic(DiagnosticSeverity.Warning, "This is a warning")
24+
};
25+
26+
string result = DiagnosticMessageHelper.JoinErrorDiagnostics(diagnostics);
27+
28+
Assert.That(result, Is.EqualTo(""));
29+
}
30+
31+
[Test]
32+
public void JoinErrorDiagnostics_SingleError_ReturnsSingleMessage()
33+
{
34+
Diagnostic[] diagnostics = new[]
35+
{
36+
CreateDiagnostic(DiagnosticSeverity.Error, "Something went wrong")
37+
};
38+
39+
string result = DiagnosticMessageHelper.JoinErrorDiagnostics(diagnostics);
40+
41+
Assert.That(result, Is.EqualTo("Something went wrong"));
42+
}
43+
44+
[Test]
45+
public void JoinErrorDiagnostics_MultipleErrors_JoinsWithSemicolon()
46+
{
47+
Diagnostic[] diagnostics = new[]
48+
{
49+
CreateDiagnostic(DiagnosticSeverity.Error, "First error"),
50+
CreateDiagnostic(DiagnosticSeverity.Error, "Second error")
51+
};
52+
53+
string result = DiagnosticMessageHelper.JoinErrorDiagnostics(diagnostics);
54+
55+
Assert.That(result, Is.EqualTo("First error; Second error"));
56+
}
57+
58+
[Test]
59+
public void JoinErrorDiagnostics_MixedSeverities_ReturnsOnlyErrors()
60+
{
61+
Diagnostic[] diagnostics = new[]
62+
{
63+
CreateDiagnostic(DiagnosticSeverity.Warning, "A warning"),
64+
CreateDiagnostic(DiagnosticSeverity.Error, "An error"),
65+
CreateDiagnostic(DiagnosticSeverity.Info, "An info")
66+
};
67+
68+
string result = DiagnosticMessageHelper.JoinErrorDiagnostics(diagnostics);
69+
70+
Assert.That(result, Is.EqualTo("An error"));
71+
}
72+
73+
private static Diagnostic CreateDiagnostic(DiagnosticSeverity severity, string message)
74+
{
75+
DiagnosticDescriptor descriptor = new(
76+
id: "TEST001",
77+
title: "Test",
78+
messageFormat: message,
79+
category: "Test",
80+
defaultSeverity: severity,
81+
isEnabledByDefault: true);
82+
83+
return Diagnostic.Create(descriptor, Location.None);
84+
}
85+
}

0 commit comments

Comments
 (0)