Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Csla.Generator.AutoImplementProperties.* nullable aware #4589

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
<IsPackable>false</IsPackable>
<BaseOutputPath>..\..\..\..\..\Bin</BaseOutputPath>
<OutputPath>..\..\..\..\..\bin\packages\</OutputPath>
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable</WarningsAsErrors>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ internal class DefinitionExtractionContext(SemanticModel _semanticModel, bool _a
/// <returns>The namespace in which the type is declared, or an empty string if it is global</returns>
public string GetTypeNamespace(TypeDeclarationSyntax typeDeclarationSyntax)
{
INamedTypeSymbol typeSymbol;

typeSymbol = _semanticModel.GetDeclaredSymbol(typeDeclarationSyntax) as INamedTypeSymbol;
var typeSymbol = _semanticModel.GetDeclaredSymbol(typeDeclarationSyntax) as INamedTypeSymbol;
if (typeSymbol is null || typeSymbol.ContainingNamespace is null) return string.Empty;
return typeSymbol.ContainingNamespace.ToString();
}
Expand All @@ -47,7 +45,7 @@ public string GetTypeNamespace(TypeDeclarationSyntax typeDeclarationSyntax)
/// <returns>The namespace in which the type is declared, or an empty string if it is global</returns>
public string GetTypeNamespace(TypeSyntax typeSyntax)
{
INamedTypeSymbol typeSymbol;
INamedTypeSymbol? typeSymbol;
if (typeSyntax is NullableTypeSyntax nullableTypeSyntax)
{
typeSyntax = nullableTypeSyntax.ElementType;
Expand Down Expand Up @@ -141,14 +139,14 @@ private bool IsMatchingTypeSymbol(INamedTypeSymbol appliedAttributeSymbol, strin
/// <returns>Boolean true if the type is decorated with the attribute, otherwise false</returns>
private bool IsPropertyDecoratedWith(PropertyDeclarationSyntax propertyDeclaration, string desiredAttributeTypeName, string desiredAttributeTypeNamespace)
{
INamedTypeSymbol appliedAttributeSymbol;

foreach (AttributeSyntax attributeSyntax in propertyDeclaration.AttributeLists.SelectMany(al => al.Attributes))
{
appliedAttributeSymbol = _semanticModel.GetTypeInfo(attributeSyntax).Type as INamedTypeSymbol;
if (IsMatchingTypeSymbol(appliedAttributeSymbol, desiredAttributeTypeName, desiredAttributeTypeNamespace))
if (_semanticModel.GetTypeInfo(attributeSyntax).Type is INamedTypeSymbol appliedAttributeSymbol)
{
return true;
if (IsMatchingTypeSymbol(appliedAttributeSymbol, desiredAttributeTypeName, desiredAttributeTypeNamespace))
{
return true;
}
}
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,16 @@ public static ExtractedPropertyDefinition ExtractPropertyDefinition(DefinitionEx
Setter = HasSetter(propertyDeclaration),
SetterModifiers = GetSetterModifiers(propertyDeclaration),
Modifiers = GetPropertyModifiers(propertyDeclaration),
Partial = IsPartial(propertyDeclaration)
Partial = IsPartial(propertyDeclaration),
TypeDefinition = new ExtractedMemberTypeDefinition
{
TypeName = GetPropertyTypeName(propertyDeclaration),
TypeNamespace = extractionContext.GetTypeNamespace(propertyDeclaration.Type),
Nullable = GetFieldTypeNullable(propertyDeclaration)
}
};
propertyDefinition.AttributeDefinitions.AddRange(GetPropertyAttributes(propertyDeclaration, extractionContext));

propertyDefinition.TypeDefinition.TypeName = GetPropertyTypeName(propertyDeclaration);
propertyDefinition.TypeDefinition.TypeNamespace = extractionContext.GetTypeNamespace(propertyDeclaration.Type);
propertyDefinition.TypeDefinition.Nullable = GetFieldTypeNullable(propertyDeclaration);

return propertyDefinition;
}

Expand Down Expand Up @@ -173,7 +175,7 @@ private static string[] GetSetterModifiers(PropertyDeclarationSyntax propertyDec
.Select(m => m.ToString())
.ToArray();

return setterModifiers;
return setterModifiers ?? [];
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ public static ExtractedTypeDefinition ExtractTypeDefinitionForInterfaces(Definit
.SelectMany(al => al.Attributes)
.FirstOrDefault(a => a.Name.ToString().StartsWith(DefinitionExtractionContext.CslaImplementPropertiesAttribute));

if (attribute != null)
if (attribute?.Name is GenericNameSyntax genericName)
{
var genericName = attribute.Name as GenericNameSyntax;
// Get the generic argument of the attribute
var genericArgument = genericName?.TypeArgumentList?.Arguments.FirstOrDefault();
var genericArgument = genericName.TypeArgumentList?.Arguments.FirstOrDefault();

if (genericArgument is null)
{
return extractedTypeDefinition;
}

// Get the type symbol of the generic argument
var semanticModel = extractionContext.SemanticModel;
Expand Down Expand Up @@ -82,25 +85,24 @@ public static ExtractedTypeDefinition ExtractTypeDefinitionForInterfaces(Definit
/// <returns>ExtractedTypeDefinition containing the data extracted from the syntax tree</returns>
public static ExtractedTypeDefinition ExtractTypeDefinition(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
{
ExtractedTypeDefinition definition = new ExtractedTypeDefinition();
StringBuilder fullyQualifiedNameBuilder = new StringBuilder();

definition.TypeName = GetTypeName(targetTypeDeclaration);
definition.TypeKind = GetTypeKind(targetTypeDeclaration);
definition.Namespace = GetNamespace(targetTypeDeclaration);
definition.Scope = GetScopeDefinition(targetTypeDeclaration);
definition.BaseClassTypeName = GetBaseClassTypeName(extractionContext, targetTypeDeclaration);
definition.DefaultPropertyModifiers = ["public"];
definition.DefaultPropertySetterModifiers = [];
var typeName = GetTypeName(targetTypeDeclaration);
ExtractedTypeDefinition definition = new ExtractedTypeDefinition
{
TypeName = typeName,
TypeKind = GetTypeKind(targetTypeDeclaration),
Namespace = GetNamespace(targetTypeDeclaration),
Scope = GetScopeDefinition(targetTypeDeclaration),
BaseClassTypeName = GetBaseClassTypeName(extractionContext, targetTypeDeclaration),
DefaultPropertyModifiers = ["public"],
DefaultPropertySetterModifiers = [],
FullyQualifiedName = typeName
};

foreach (ExtractedPropertyDefinition propertyDefinition in PropertyDefinitionsExtractor.ExtractPropertyDefinitions(extractionContext, targetTypeDeclaration))
{
definition.Properties.Add(propertyDefinition);
}

fullyQualifiedNameBuilder.Append(definition.TypeName);
definition.FullyQualifiedName = fullyQualifiedNameBuilder.ToString();

return definition;
}

Expand All @@ -119,12 +121,7 @@ private static string GetBaseClassTypeName(DefinitionExtractionContext extractio
var targetTypeSymbol = extractionContext.SemanticModel.GetDeclaredSymbol(targetTypeDeclaration) as INamedTypeSymbol;
var baseTypeSymbol = targetTypeSymbol?.BaseType;

if (baseTypeSymbol != null)
{
return baseTypeSymbol.Name;
}

return null;
return baseTypeSymbol?.Name ?? string.Empty;
}

#endregion
Expand All @@ -144,13 +141,11 @@ private static string GetNamespace(TypeDeclarationSyntax targetTypeDeclaration)

// Get the containing syntax node for the type declaration
// (could be a nested type, for example)
SyntaxNode potentialNamespaceParent = targetTypeDeclaration.Parent;
SyntaxNode? potentialNamespaceParent = targetTypeDeclaration.Parent;

// Keep moving "out" of nested classes etc until we get to a namespace
// or until we run out of parents
while (potentialNamespaceParent != null &&
potentialNamespaceParent is not NamespaceDeclarationSyntax
&& potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax)
while (potentialNamespaceParent != null && potentialNamespaceParent is not NamespaceDeclarationSyntax && potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax)
{
potentialNamespaceParent = potentialNamespaceParent.Parent;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ public class ExtractedAttributeDefinition : IEquatable<ExtractedAttributeDefinit
/// <summary>
/// The name of the attribute.
/// </summary>
public string AttributeName { get; set; }
public string AttributeName { get; set; } = string.Empty;

/// <summary>
/// The namespace of the attribute.
/// </summary>
public string AttributeNamespace { get; set; }
public string AttributeNamespace { get; set; } = string.Empty;

/// <summary>
/// A list of arguments passed to the attribute's constructor.
Expand All @@ -27,9 +27,9 @@ public class ExtractedAttributeDefinition : IEquatable<ExtractedAttributeDefinit
/// </summary>
/// <param name="other">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>
public bool Equals(ExtractedAttributeDefinition other)
public bool Equals(ExtractedAttributeDefinition? other)
{
if (ReferenceEquals(null, other))
if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
Expand All @@ -42,9 +42,9 @@ public bool Equals(ExtractedAttributeDefinition other)
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj))
if (obj is null)
return false;
if (ReferenceEquals(this, obj))
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ public class ExtractedMemberTypeDefinition : IEquatable<ExtractedMemberTypeDefin
/// <summary>
/// The name of the type
/// </summary>
public string TypeName { get; set; }
public required string TypeName { get; set; }

/// <summary>
/// The namespace in which the type is defined
/// </summary>
public string TypeNamespace { get; set; }
public required string TypeNamespace { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the type is nullable.
Expand All @@ -25,7 +25,7 @@ public class ExtractedMemberTypeDefinition : IEquatable<ExtractedMemberTypeDefin
/// </summary>
/// <param name="other">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>
public bool Equals(ExtractedMemberTypeDefinition other)
public bool Equals(ExtractedMemberTypeDefinition? other)
{
if (other == null)
return false;
Expand All @@ -41,7 +41,7 @@ public bool Equals(ExtractedMemberTypeDefinition other)
/// <param name="obj">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>

public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (obj is ExtractedMemberTypeDefinition other)
return Equals(other);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ public class ExtractedPropertyDefinition : IMemberDefinition, IEquatable<Extract
/// <summary>
/// The name of the property
/// </summary>
public string PropertyName { get; set; }
public required string PropertyName { get; init; }

/// <summary>
/// The definition of the type of this property
/// </summary>
public ExtractedMemberTypeDefinition TypeDefinition { get; } = new();
public required ExtractedMemberTypeDefinition TypeDefinition { get; init; }

/// <summary>
/// The member name for the field
Expand All @@ -49,7 +49,7 @@ public class ExtractedPropertyDefinition : IMemberDefinition, IEquatable<Extract
/// <summary>
/// The modifiers for this property
/// </summary>
public string[] Modifiers { get; internal set; }
public string[] Modifiers { get; internal set; } = [];

/// <summary>
/// Gets or sets a value indicating whether this property is partial.
Expand All @@ -59,14 +59,14 @@ public class ExtractedPropertyDefinition : IMemberDefinition, IEquatable<Extract
/// <summary>
/// The modifiers for the setter of this property
/// </summary>
public string[] SetterModifiers { get; internal set; }
public string[] SetterModifiers { get; internal set; } = [];

/// <summary>
/// Determines whether the specified object is equal to the current object.
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns>True if the specified object is equal to the current object; otherwise, false.</returns>
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return Equals(obj as ExtractedPropertyDefinition);
}
Expand All @@ -76,7 +76,7 @@ public override bool Equals(object obj)
/// </summary>
/// <param name="other">The ExtractedPropertyDefinition to compare with the current ExtractedPropertyDefinition.</param>
/// <returns>True if the specified ExtractedPropertyDefinition is equal to the current ExtractedPropertyDefinition; otherwise, false.</returns>
public bool Equals(ExtractedPropertyDefinition other)
public bool Equals(ExtractedPropertyDefinition? other)
{
if (other == null)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,54 @@ public class ExtractedTypeDefinition : IEquatable<ExtractedTypeDefinition>
/// <summary>
/// The namespace in which the type resides
/// </summary>
public string Namespace { get; set; }
public required string Namespace { get; init; }

/// <summary>
/// The scope of the class
/// </summary>
public string Scope { get; set; } = "public";
public required string Scope { get; init; } = "public";

/// <summary>
/// The name of the type, excluding any namespace
/// </summary>
public string TypeName { get; set; }
public required string TypeName { get; set; }

/// <summary>
/// The name of the kind of type being represented
/// </summary>
public string TypeKind { get; set; }
public required string TypeKind { get; set; }

/// <summary>
/// The fully qualified name of the type, including namespace
/// </summary>
public string FullyQualifiedName { get; set; }
public required string FullyQualifiedName { get; set; }

/// <summary>
/// The properties to be included in auto implementation
/// </summary>
public IList<ExtractedPropertyDefinition> Properties { get; private set; } = new List<ExtractedPropertyDefinition>();
public IList<ExtractedPropertyDefinition> Properties { get; private set; } = [];

/// <summary>
/// The name of the base class for the type
/// </summary>
public string BaseClassTypeName { get; internal set; }
public required string BaseClassTypeName { get; init; }

/// <summary>
/// The modifiers for this property
/// </summary>
public string[] DefaultPropertyModifiers { get; internal set; }
public string[] DefaultPropertyModifiers { get; internal set; } = [];

/// <summary>
/// The modifiers for the setter of this property
/// </summary>
public string[] DefaultPropertySetterModifiers { get; internal set; }
public required string[] DefaultPropertySetterModifiers { get; init; }

/// <summary>
/// Determines whether the current <see cref="ExtractedTypeDefinition"/> object is equal to another object of the same type.
/// </summary>
/// <param name="other">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>
public bool Equals(ExtractedTypeDefinition other)
public bool Equals(ExtractedTypeDefinition? other)
{
if (other == null)
return false;
Expand All @@ -80,7 +81,7 @@ public bool Equals(ExtractedTypeDefinition other)
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ public class GenerationResults
/// <summary>
/// The fully qualified name of the generated type
/// </summary>
public string FullyQualifiedName { get; set; }
public required string FullyQualifiedName { get; set; }

/// <summary>
/// The source code that has been generated by the builder
/// </summary>
public string GeneratedSource { get; set; }
public required string GeneratedSource { get; set; }

}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
{
return TypeDefinitionExtractor.ExtractTypeDefinitionForInterfaces(new DefinitionExtractionContext(ctx.SemanticModel, true, false), typeDeclarationSyntax);
}
return null;
return default!;
})
.Where(static m => m is not null).WithTrackingName(TrackingNames.ExtractClasses);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
{
return TypeDefinitionExtractor.ExtractTypeDefinition(new DefinitionExtractionContext(ctx.SemanticModel, false, true), typeDeclarationSyntax);
}
return null;
return default!;
})
.Where(static m => m is not null).WithTrackingName(TrackingNames.ExtractClasses);

Expand Down
Loading
Loading