Skip to content

Commit

Permalink
Improved performance 3x
Browse files Browse the repository at this point in the history
  • Loading branch information
pmrogala committed Nov 1, 2024
1 parent 628d9ce commit 8afc74c
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 34 deletions.
60 changes: 26 additions & 34 deletions Buildenator/BuildersGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,28 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
#if DEBUG
// Debugger.Launch();
#endif
var symbolsAndAttributes = context.SyntaxProvider.ForAttributeWithMetadataName(
typeof(MakeBuilderAttribute).FullName,
predicate: static (sx, _) => sx is ClassDeclarationSyntax,
transform: static (ctx, _) =>
{
var attributes = ctx.TargetSymbol.GetAttributes();
return (
BuilderSymbol: (INamedTypeSymbol)ctx.TargetSymbol,
BuilderAttribute: new MakeBuilderAttributeInternal(
attributes.Single(
attributeData => attributeData.AttributeClass?.Name == nameof(MakeBuilderAttribute))),
MockingAttribute: GetMockingConfigurationOrDefault(attributes),
FixtureAttribute: GetLocalFixturePropertiesOrDefault(attributes)
);
}
);

var nullableOptions = context.CompilationProvider
.Select(static (compilation, _) => compilation.Options.NullableContextOptions);
var syntaxTrees = context.CompilationProvider
.SelectMany(static (compilation, _) => compilation.SyntaxTrees);

var symbolsAndAttributes = syntaxTrees
.Combine(context.CompilationProvider)
.Select(SelectSyntaxTreeAndSemanticModel)
.Select(static (tuple, ct) => (Root: tuple.SyntaxTree.GetRoot(ct), tuple.SemanticModel))
.SelectMany(static (tuple, _) =>
tuple.Root.DescendantNodesAndSelf().Select(node => (node, tuple.SemanticModel)))
.Where(static tuple => tuple.node is ClassDeclarationSyntax)
.Select(static (tuple, token) => tuple.SemanticModel.GetDeclaredSymbol(tuple.node, token))
.Where(static symbol => symbol is INamedTypeSymbol)
.Select(static (symbol, _) => (INamedTypeSymbol)symbol!)
.Select(static (symbol, _) => (Symbol: symbol, Attributes: symbol.GetAttributes()))
.Select(static (symbolAndAttributesTuple, _)
=> (symbolAndAttributesTuple.Symbol,
Attribute: symbolAndAttributesTuple.Attributes.SingleOrDefault(attributeData =>
attributeData.AttributeClass?.Name == nameof(MakeBuilderAttribute))))
.Where(static tuple => tuple.Attribute is not null /* remember about the bang operator in the next line when removing this condition */)
.Select(static (tuple, _) => (BuilderSymbol: tuple.Symbol, Attribute: new MakeBuilderAttributeInternal(tuple.Attribute!)));

var classSymbols = symbolsAndAttributes
.Where(tuple => !tuple.Attribute.TypeForBuilder.IsAbstract);
.Where(tuple => !tuple.BuilderAttribute.TypeForBuilder.IsAbstract);

var configurationBuilders = context.CompilationProvider
.Select(static (c, _) => c.Assembly)
Expand All @@ -76,6 +72,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
var globalFixtureProperties = assembly.Fixture?.ConstructorArguments;
var mockingConfigurationBuilder = assembly.Mocking?.ConstructorArguments;
var globalBuilderProperties = assembly.Builder?.ConstructorArguments;
return (globalFixtureProperties, mockingConfigurationBuilder, globalBuilderProperties);
});

Expand All @@ -84,27 +81,22 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
.Combine(nullableOptions)
.Select(static (leftRightAndNullable, _) =>
{
var (builderNamedTypeSymbol, attribute) = leftRightAndNullable.Left.Left;
var (builderNamedTypeSymbol, builderAttribute, mockingAttribute, fixtureAttribute) = leftRightAndNullable.Left.Left;
var (globalFixtureProperties,
globalMockingConfiguration,
globalBuilderProperties) = leftRightAndNullable.Left.Right;
var nullableOptions = leftRightAndNullable.Right;
var builderAttributes = builderNamedTypeSymbol.GetAttributes();
var mockingProperties = MockingProperties.CreateOrDefault(
globalMockingConfiguration,
GetMockingConfigurationOrDefault(builderAttributes));
var mockingProperties = MockingProperties.CreateOrDefault(globalMockingConfiguration, mockingAttribute);
var fixtureProperties =
FixtureProperties.CreateOrDefault(
globalFixtureProperties,
GetLocalFixturePropertiesOrDefault(builderAttributes));
FixtureProperties.CreateOrDefault(globalFixtureProperties, fixtureAttribute);
var builderProperties =
BuilderProperties.Create(builderNamedTypeSymbol, attribute, globalBuilderProperties, nullableOptions.AnnotationsEnabled());
BuilderProperties.Create(builderNamedTypeSymbol, builderAttribute, globalBuilderProperties, nullableOptions.AnnotationsEnabled());
return (fixtureProperties, mockingConfiguration: mockingProperties, builderProperties,
attribute.TypeForBuilder);
builderAttribute.TypeForBuilder);
})
.Select(static (properties, _) =>
{
Expand All @@ -124,16 +116,16 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
{
productionContext.AddCsSourceFile(generator.FileName,
SourceText.From(generator.CreateBuilderCode(), Encoding.UTF8));
foreach(var diagnostic in generator.Diagnostics)
foreach (var diagnostic in generator.Diagnostics)
{
productionContext.ReportDiagnostic(diagnostic);
}
});


var abstractClassSymbols = symbolsAndAttributes
.Where(tuple => tuple.Attribute.TypeForBuilder.IsAbstract)
.Select((tuple, _) => (tuple.BuilderSymbol, tuple.Attribute.TypeForBuilder));
.Where(tuple => tuple.BuilderAttribute.TypeForBuilder.IsAbstract)
.Select((tuple, _) => (tuple.BuilderSymbol, tuple.BuilderAttribute.TypeForBuilder));

context.RegisterSourceOutput(abstractClassSymbols, (productionContext, tuple)
=>
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This version brings many breaking changes.
- Changed `defaultStaticCreator` to `generateDefaultBuildMethod` to better reflect the intention.
- Removed generating the namespace of an entity that is build by a builder to handle edge cases.
- It shouldn't generate any regression, but it's a breaking change anyway.
- **Improved performance 3x**


## 8.3.0.0 - 2024-10-30
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace Buildenator.IntegrationTests.Source.Attributes
{
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class MakeBuilderAttribute : Attribute
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Buildenator.IntegrationTests.Source.Attributes;

namespace Buildenator.IntegrationTests.Source.Builders
{
[MakeBuilder]
internal partial class FakeBuilder
{
}
}

0 comments on commit 8afc74c

Please sign in to comment.