Skip to content

Commit

Permalink
Slightly improved perf of source gen and analyzers
Browse files Browse the repository at this point in the history
  • Loading branch information
PawelGerr committed Dec 11, 2024
1 parent 4e4070d commit b65d089
Show file tree
Hide file tree
Showing 16 changed files with 81 additions and 84 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<Copyright>(c) $([System.DateTime]::Now.Year), Pawel Gerr. All rights reserved.</Copyright>
<VersionPrefix>8.0.0</VersionPrefix>
<VersionPrefix>8.0.1</VersionPrefix>
<Authors>Pawel Gerr</Authors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageProjectUrl>https://github.com/PawelGerr/Thinktecture.Runtime.Extensions</PackageProjectUrl>
Expand Down
1 change: 1 addition & 0 deletions samples/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<IsPackable>false</IsPackable>
<ImplicitUsings>disable</ImplicitUsings>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<ReportAnalyzer>true</ReportAnalyzer>
<ThinktectureRuntimeExtensions_SourceGenerator_LogFilePathMustBeUnique>false</ThinktectureRuntimeExtensions_SourceGenerator_LogFilePathMustBeUnique>
<ThinktectureRuntimeExtensions_SourceGenerator_LogFilePath>C:\temp\ttre_samples_logs.txt</ThinktectureRuntimeExtensions_SourceGenerator_LogFilePath>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ private bool IsUnionCandidate(TypeDeclarationSyntax typeDeclaration)
return null;
}

if (attributeType.TypeArguments.Length < 2)
if (attributeType.Arity < 2)
{
Logger.LogDebug($"Expected the attribute type to have at least 2 type arguments but found {attributeType.TypeArguments.Length.ToString()}", tds);
Logger.LogDebug($"Expected the attribute type to have at least 2 type arguments but found {attributeType.Arity.ToString()}", tds);
return null;
}

Expand All @@ -140,9 +140,9 @@ private bool IsUnionCandidate(TypeDeclarationSyntax typeDeclaration)
return new SourceGenContext(new SourceGenError("Could not fetch type information for code generation of a discriminated union", tds));

var settings = new AdHocUnionSettings(context.Attributes[0],
attributeType.TypeArguments.Length,
attributeType.Arity,
attributeInfo);
var memberTypeStates = new AdHocUnionMemberTypeState[attributeType.TypeArguments.Length];
var memberTypeStates = attributeType.Arity == 0 ? [] : new AdHocUnionMemberTypeState[attributeType.Arity];

for (var i = 0; i < attributeType.TypeArguments.Length; i++)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ private static void AnalyzeMethodCall(OperationAnalysisContext context)
if (declaredType.IsEnum(out var attribute))
{
var isValidatable = attribute.FindIsValidatable() ?? false;
var nonIgnoredMembers = declaredType.GetNonIgnoredMembers();
var items = declaredType.GetEnumItems(nonIgnoredMembers);
var items = declaredType.GetEnumItems();

AnalyzeEnumSwitchMap(context,
items,
Expand Down Expand Up @@ -482,16 +481,15 @@ private static void ValidateCustomKeyMemberImplementation(
TypeMustBePartial(context, type);
TypeMustNotBeGeneric(context, type, locationOfFirstDeclaration, "Value Object");

var nonIgnoredItems = type.GetNonIgnoredMembers();
var assignableMembers = type.GetAssignableFieldsAndPropertiesAndCheckForReadOnly(nonIgnoredItems, factory, false, true, context.CancellationToken, context)
var assignableMembers = type.GetAssignableFieldsAndPropertiesAndCheckForReadOnly(factory, false, true, context.CancellationToken, context)
.Where(m => !m.IsStatic)
.ToList();

var baseClass = type.BaseType;

while (!baseClass.IsNullOrObject())
{
baseClass.IterateAssignableFieldsAndPropertiesAndCheckForReadOnly(baseClass.GetNonIgnoredMembers(), false, context.CancellationToken, locationOfFirstDeclaration, context).Enumerate();
baseClass.IterateAssignableFieldsAndPropertiesAndCheckForReadOnly(false, context.CancellationToken, locationOfFirstDeclaration, context).Enumerate();

baseClass = baseClass.BaseType;
}
Expand Down Expand Up @@ -557,22 +555,21 @@ private static void ValidateEnum(
TypeMustBePartial(context, enumType);
TypeMustNotBeGeneric(context, enumType, locationOfFirstDeclaration, "Enumeration");

var nonIgnoredMembers = enumType.GetNonIgnoredMembers();
var items = enumType.GetEnumItems(nonIgnoredMembers);
var items = enumType.GetEnumItems();

if (items.Length == 0)
ReportDiagnostic(context, DiagnosticsDescriptors.EnumerationHasNoItems, locationOfFirstDeclaration, enumType);

Check_ItemLike_StaticProperties(context, enumType, nonIgnoredMembers);
Check_ItemLike_StaticProperties(context, enumType);
EnumItemsMustBePublic(context, enumType, items);

_ = enumType.GetAssignableFieldsAndPropertiesAndCheckForReadOnly(nonIgnoredMembers, factory, false, false, context.CancellationToken, context).ToList();
_ = enumType.GetAssignableFieldsAndPropertiesAndCheckForReadOnly(factory, false, false, context.CancellationToken, context).ToList();

var baseClass = enumType.BaseType;

while (!baseClass.IsNullOrObject())
{
baseClass.IterateAssignableFieldsAndPropertiesAndCheckForReadOnly(baseClass.GetNonIgnoredMembers(), false, context.CancellationToken, locationOfFirstDeclaration, context).Enumerate();
baseClass.IterateAssignableFieldsAndPropertiesAndCheckForReadOnly(false, context.CancellationToken, locationOfFirstDeclaration, context).Enumerate();

baseClass = baseClass.BaseType;
}
Expand All @@ -581,14 +578,13 @@ private static void ValidateEnum(

EnumKeyMemberNameMustNotBeItem(context, attribute, locationOfFirstDeclaration);

ValidateKeyedSmartEnum(context, enumType, attribute, nonIgnoredMembers, locationOfFirstDeclaration);
ValidateKeyedSmartEnum(context, enumType, attribute, locationOfFirstDeclaration);
}

private static void ValidateKeyedSmartEnum(
OperationAnalysisContext context,
INamedTypeSymbol enumType,
IObjectCreationOperation attribute,
ImmutableArray<ISymbol> nonIgnoredMembers,
Location locationOfFirstDeclaration)
{
var keyType = (attribute.Type as INamedTypeSymbol)?.TypeArguments.FirstOrDefault();
Expand All @@ -609,7 +605,7 @@ private static void ValidateKeyedSmartEnum(

if (isValidatable)
{
ValidateCreateInvalidItem(context, enumType, keyType, nonIgnoredMembers, locationOfFirstDeclaration);
ValidateCreateInvalidItem(context, enumType, keyType, locationOfFirstDeclaration);
}
else if (enumType.IsValueType)
{
Expand All @@ -627,14 +623,15 @@ private static void TypeMustNotBeGeneric(OperationAnalysisContext context, IName

private static void Check_ItemLike_StaticProperties(
OperationAnalysisContext context,
INamedTypeSymbol enumType,
ImmutableArray<ISymbol> nonIgnoredMembers)
INamedTypeSymbol enumType)
{
for (var i = 0; i < nonIgnoredMembers.Length; i++)
var members = enumType.GetMembers();

for (var i = 0; i < members.Length; i++)
{
var member = nonIgnoredMembers[i];
var member = members[i];

if (member.IsStatic && member is IPropertySymbol property && SymbolEqualityComparer.Default.Equals(property.Type, enumType))
if (member.IsStatic && member is IPropertySymbol property && SymbolEqualityComparer.Default.Equals(property.Type, enumType) && !property.IsIgnored())
ReportDiagnostic(context, DiagnosticsDescriptors.StaticPropertiesAreNotConsideredItems, property.GetIdentifier(context.CancellationToken)?.GetLocation() ?? Location.None, property.Name);
}
}
Expand Down Expand Up @@ -680,10 +677,9 @@ private static void ValidateCreateInvalidItem(
OperationAnalysisContext context,
INamedTypeSymbol enumType,
ITypeSymbol keyType,
ImmutableArray<ISymbol> nonIgnoredMembers,
Location location)
{
var hasCreateInvalidItemImplementation = enumType.HasCreateInvalidItemImplementation(nonIgnoredMembers, keyType, context.CancellationToken, context);
var hasCreateInvalidItemImplementation = enumType.HasCreateInvalidItemImplementation(keyType, context.CancellationToken, context);

if (!hasCreateInvalidItemImplementation && enumType.IsAbstract)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public EnumSourceGeneratorState(
INamedTypeSymbol type,
KeyMemberState? keyMember,
ValidationErrorState validationError,
ImmutableArray<ISymbol> nonIgnoredMembers,
EnumSettings settings,
bool hasCreateInvalidItemImplementation,
bool hasDerivedTypes,
Expand All @@ -53,8 +52,8 @@ public EnumSourceGeneratorState(
IsAbstract = type.IsAbstract;

BaseType = type.GetBaseType(factory);
Items = new EnumItems(type.GetEnumItems(nonIgnoredMembers));
AssignableInstanceFieldsAndProperties = type.GetAssignableFieldsAndPropertiesAndCheckForReadOnly(nonIgnoredMembers, factory, true, false, cancellationToken).ToList();
Items = new EnumItems(type.GetEnumItems());
AssignableInstanceFieldsAndProperties = type.GetAssignableFieldsAndPropertiesAndCheckForReadOnly(factory, true, false, cancellationToken).ToList();
}

public override bool Equals(object? obj)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,9 @@ private bool IsEnumCandidate(TypeDeclarationSyntax typeDeclaration)
return null;
}

if (attributetype.TypeArguments.Length != 1)
if (attributetype.Arity != 1)
{
Logger.LogDebug($"Expected the attribute type to have 1 type argument but found {attributetype.TypeArguments.Length.ToString()}", tds);
Logger.LogDebug($"Expected the attribute type to have 1 type argument but found {attributetype.Arity.ToString()}", tds);
return null;
}

Expand Down Expand Up @@ -393,15 +393,13 @@ private bool IsEnumCandidate(TypeDeclarationSyntax typeDeclaration)
keyMember = settings.CreateKeyMember(keyTypedMemberState);
}

var nonIgnoredMembers = type.GetNonIgnoredMembers();
var hasCreateInvalidItemImplementation = keyMemberType is not null && settings.IsValidatable && type.HasCreateInvalidItemImplementation(nonIgnoredMembers, keyMemberType, cancellationToken);
var hasCreateInvalidItemImplementation = keyMemberType is not null && settings.IsValidatable && type.HasCreateInvalidItemImplementation(keyMemberType, cancellationToken);

var derivedTypeNames = FindDerivedTypes(type);
var enumState = new EnumSourceGeneratorState(factory,
type,
keyMember,
attributeInfo.ValidationError,
nonIgnoredMembers,
new EnumSettings(settings, attributeInfo),
hasCreateInvalidItemImplementation,
derivedTypeNames.Count > 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,13 @@ public TypedMemberState(ITypeSymbol type)

private static bool IsToStringNullable(ITypeSymbol type)
{
var array = type.GetMembers();
var array = type.GetMembers("ToString");

for (var i = 0; i < array.Length; i++)
{
var member = array[i];

if (member is not IMethodSymbol { Name: "ToString" } toString)
if (member is not IMethodSymbol toString)
continue;

return toString.ReturnNullableAnnotation == NullableAnnotation.Annotated;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public UnionSourceGenState(
Namespace = type.ContainingNamespace?.IsGlobalNamespace == true ? null : type.ContainingNamespace?.ToString();
HasNonDefaultConstructor = !type.Constructors.IsDefaultOrEmpty && type.Constructors.Any(c => !c.IsImplicitlyDeclared);
ContainingTypes = type.GetContainingTypes();
GenericsFullyQualified = type.TypeArguments.Length == 0
GenericsFullyQualified = type.Arity == 0
? []
: type.TypeArguments.Select(t => t.ToFullyQualifiedDisplayString()).ToList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ private bool IsCandidate(SyntaxNode syntaxNode, CancellationToken cancellationTo
return null;
}

if (attributeType.TypeArguments.Length != 0)
if (attributeType.Arity != 0)
{
Logger.LogDebug($"Expected the union attribute type to have no type arguments but found {attributeType.TypeArguments.Length.ToString()}", tds);
Logger.LogDebug($"Expected the union attribute type to have no type arguments but found {attributeType.Arity.ToString()}", tds);
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,10 @@ public ComplexValueObjectSourceGeneratorState(
NullableAnnotation = type.NullableAnnotation;
IsNullableStruct = type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T;

var nonIgnoredMembers = type.GetNonIgnoredMembers();
AssignableInstanceFieldsAndProperties = type.GetAssignableFieldsAndPropertiesAndCheckForReadOnly(nonIgnoredMembers, factory, true, true, cancellationToken).ToList();
AssignableInstanceFieldsAndProperties = type.GetAssignableFieldsAndPropertiesAndCheckForReadOnly(factory, true, true, cancellationToken).ToList();
EqualityMembers = GetEqualityMembers();

var factoryValidationReturnType = nonIgnoredMembers.IsDefaultOrEmpty
? null
: (nonIgnoredMembers.FirstOrDefault(m => m.IsStatic && m.Name == Constants.Methods.VALIDATE_FACTORY_ARGUMENTS && m is IMethodSymbol method && method.ReturnType.SpecialType != SpecialType.System_Void) as IMethodSymbol)?.ReturnType;
var factoryValidationReturnType = (type.GetMembers().FirstOrDefault(m => m.IsStatic && m.Name == Constants.Methods.VALIDATE_FACTORY_ARGUMENTS && m is IMethodSymbol method && method.ReturnType.SpecialType != SpecialType.System_Void) as IMethodSymbol)?.ReturnType;

if (factoryValidationReturnType is not null)
FactoryValidationReturnType = factoryValidationReturnType.ToFullyQualifiedDisplayString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ public KeyedValueObjectSourceGeneratorState(
NullableAnnotation = type.NullableAnnotation;
IsNullableStruct = type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T;

var nonIgnoredMembers = type.GetNonIgnoredMembers();
var members = type.GetMembers();

for (var i = 0; i < nonIgnoredMembers.Length; i++)
for (var i = 0; i < members.Length; i++)
{
var member = nonIgnoredMembers[i];
var member = members[i];

if (member.IsValidateFactoryArgumentsImplementation(out var method) && method.ReturnType.SpecialType != SpecialType.System_Void)
FactoryValidationReturnType = method.ReturnType.ToFullyQualifiedDisplayString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,9 @@ private bool IsValueObjectCandidate(TypeDeclarationSyntax typeDeclaration)
return null;
}

if (attributeType.TypeArguments.Length != 1)
if (attributeType.Arity != 1)
{
Logger.LogDebug($"Expected the attribute type to have 1 type argument but found {attributeType.TypeArguments.Length.ToString()}", tds);
Logger.LogDebug($"Expected the attribute type to have 1 type argument but found {attributeType.Arity.ToString()}", tds);
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ namespace Thinktecture;

public static class SymbolExtensions
{
public static AttributeData? FindAttribute(this ISymbol type, Func<INamedTypeSymbol, bool> predicate)
public static AttributeData? FindAttribute(this ISymbol symbol, Func<INamedTypeSymbol, bool> predicate)
{
var attributes = type.GetAttributes();
var attributes = symbol.GetAttributes();

if (attributes.IsDefaultOrEmpty)
return null;
Expand All @@ -28,9 +28,14 @@ public static bool HasAttribute(this ISymbol symbol, Func<INamedTypeSymbol, bool
return symbol.FindAttribute(predicate) is not null;
}

public static bool IsIgnored(this ISymbol member)
public static bool IsIgnored(this IFieldSymbol field)
{
return member.HasAttribute(static attrType => attrType.IsValueObjectMemberIgnoreAttribute());
return field.HasAttribute(static attrType => attrType.IsValueObjectMemberIgnoreAttribute());
}

public static bool IsIgnored(this IPropertySymbol property)
{
return property.HasAttribute(static attrType => attrType.IsValueObjectMemberIgnoreAttribute());
}

public static bool IsValidateFactoryArgumentsImplementation(
Expand Down
Loading

0 comments on commit b65d089

Please sign in to comment.