Skip to content

Commit

Permalink
Add primary constructor & Record parameter list
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviersolau committed Feb 13, 2024
1 parent 7c90bd0 commit 0493322
Show file tree
Hide file tree
Showing 42 changed files with 390 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public interface IDeclaration<out TNode>
/// </summary>
bool IsValueType { get; }

/// <summary>
/// Tells if this is a record type.
/// </summary>
bool IsRecordType { get; }

/// <summary>
/// Gets the declaration syntax node provider.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,15 @@ public abstract class ADeclaration<TNode> : ADeclaration, IDeclaration<TNode>
/// <param name="usingDirectives">The current using directive available for this class.</param>
/// <param name="location">The location of the declaration.</param>
/// <param name="isValueType">Tells if this is a valueType.</param>
/// <param name="isRecordType">Tells if this is a record type.</param>
protected ADeclaration(
string nameSpace,
string name,
ISyntaxNodeProvider<TNode> syntaxNodeProvider,
IUsingDirectives usingDirectives,
string location,
bool isValueType)
bool isValueType,
bool isRecordType)
{
DeclarationNameSpace = nameSpace;
Name = name;
Expand All @@ -77,6 +79,7 @@ protected ADeclaration(
FullName = GetFullName(nameSpace, name);
Location = location;
IsValueType = isValueType;
IsRecordType = isRecordType;
}

/// <inheritdoc/>
Expand All @@ -91,6 +94,9 @@ protected ADeclaration(
/// <inheritdoc/>
public bool IsValueType { get; protected set; }

/// <inheritdoc/>
public bool IsRecordType { get; protected set; }

/// <inheritdoc/>
public ISyntaxNodeProvider<TNode> SyntaxNodeProvider { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,17 @@ public abstract class AGenericDeclaration<TNode> : ADeclaration<TNode>, IGeneric
/// <param name="location">The location of the declaration.</param>
/// <param name="loader">The loader to use when deep loading the declaration.</param>
/// <param name="isValueType">Tells if this is a valueType.</param>
/// <param name="isRecordType">Tells if this is a record type.</param>
protected AGenericDeclaration(
string nameSpace,
string name,
ISyntaxNodeProvider<TNode> syntaxNodeProvider,
IUsingDirectives usingDirectives,
string location,
AGenericDeclarationLoader<TNode> loader,
bool isValueType)
: base(nameSpace, name, syntaxNodeProvider, usingDirectives, location, isValueType)
bool isValueType,
bool isRecordType)
: base(nameSpace, name, syntaxNodeProvider, usingDirectives, location, isValueType, isRecordType)
{
this.loader = loader;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public ClassDeclaration(
usingDirectives,
location,
loader,
false,
false)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public EnumDeclaration(
IUsingDirectives usingDirectives,
string location,
AEnumDeclarationLoader loader)
: base(nameSpace, name, syntaxNodeProvider, usingDirectives, location, true)
: base(nameSpace, name, syntaxNodeProvider, usingDirectives, location, true, false)
{
this.loader = loader;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class GenericParameterDeclaration : ADeclaration<TypeParameterSyntax>, IG
/// <param name="name">The declaration name.</param>
/// <param name="syntaxNodeProvider">The declaration syntax node provider.</param>
public GenericParameterDeclaration(string name, ISyntaxNodeProvider<TypeParameterSyntax> syntaxNodeProvider)
: base(string.Empty, name, syntaxNodeProvider, NoUsingDirectives.Instance, null, false)
: base(string.Empty, name, syntaxNodeProvider, NoUsingDirectives.Instance, null, false, false)
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public InterfaceDeclaration(
usingDirectives,
location,
loader,
false,
false)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,21 @@ private static void LoadProperties(

var attributeList = LoadCustomAttributes(metadataReader, declaration, resolver, customAttributeHandles);

var propertyType = propertySignature.ReturnType;

memberList.Add(
new PropertyDeclaration(
propertyName,
propertyType,
new MetadataPropertySyntaxNodeProvider<PropertyDeclarationSyntax>(),
attributeList,
!getterHandle.IsNil,
!setterHandle.IsNil));
var compilerAttribute = attributeList.FirstOrDefault(attribute => attribute.DeclarationUse.Declaration.FullName == typeof(CompilerGeneratedAttribute).FullName);

if (compilerAttribute == null)
{
var propertyType = propertySignature.ReturnType;

memberList.Add(
new PropertyDeclaration(
propertyName,
propertyType,
new MetadataPropertySyntaxNodeProvider<PropertyDeclarationSyntax>(),
attributeList,
!getterHandle.IsNil,
!setterHandle.IsNil));
}
}
}

Expand Down Expand Up @@ -327,13 +332,15 @@ private static void LoadExtends(MetadataReader metadataReader, AGenericDeclarati
}
}

var extendedInterfaceFilter = BuildExtendedInterfaceFilter(metadataReader, typeDefinition, declaration.IsValueType);

foreach (var interfaceImplementation in typeDefinition.GetInterfaceImplementations())
{
if (!interfaceImplementation.IsNil)
{
var interfaceDeclarationUse = GetDeclarationUseFrom(metadataReader, interfaceImplementation, resolver, declaration);

if (interfaceDeclarationUse != null)
if (interfaceDeclarationUse != null && extendedInterfaceFilter(interfaceDeclarationUse))
{
uses.Add(interfaceDeclarationUse);
}
Expand All @@ -343,6 +350,26 @@ private static void LoadExtends(MetadataReader metadataReader, AGenericDeclarati
declaration.Extends = uses;
}

private static Func<IDeclarationUse<SyntaxNode>, bool> BuildExtendedInterfaceFilter(MetadataReader metadataReader, TypeDefinition typeDefinition, bool valueType)
{
if ((valueType && ProbeRecordStructType(metadataReader, typeDefinition)) || (!valueType && ProbeRecordType(metadataReader, typeDefinition)))
{
// IEquatable must be excluded since it is compiler generated on record type.
var equatableFullName = GetNameWithoutGeneric(typeof(IEquatable<>).FullName);
return t =>
{
if (t.Declaration.FullName == equatableFullName)
{
return false;
}
return true;
};
}

return t => true;
}


private static void LoadGenericParameters(MetadataReader metadataReader, AGenericDeclaration<TNode> declaration, IDeclarationResolver resolver)
{
var typeDefinitionHandle = declaration.GetData<TypeDefinitionHandle>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,23 @@ public ParserGenericDeclarationLoader(IGeneratorLogger<ParserGenericDeclarationL

internal override void Load(AGenericDeclaration<TNode> declaration, IDeclarationResolver resolver)
{
LoadGenericParameters(declaration);
LoadExtends(declaration, resolver);
LoadMembers(declaration, resolver);
LoadAttributes(declaration, resolver);
try
{
LoadGenericParameters(declaration);
LoadExtends(declaration, resolver);
LoadMembers(declaration, resolver);
LoadAttributes(declaration, resolver);
}
catch
{
// Make sure all collection are assigned.
declaration.GenericParameters ??= Array.Empty<IGenericParameterDeclaration>();
declaration.Extends ??= Array.Empty<IDeclarationUse<SyntaxNode>>();
declaration.Members ??= Array.Empty<IMemberDeclaration<SyntaxNode>>();
declaration.Attributes ??= Array.Empty<IAttributeUse>();

throw;
}
}

internal override ISyntaxNodeProvider<TypeParameterListSyntax> GetTypeParameterListSyntaxProvider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,16 +324,21 @@ private static void LoadExtends(AGenericDeclaration<TNode> declaration, IDeclara
{
var uses = new List<IDeclarationUse<SyntaxNode>>();

if (declarationType.BaseType != null)
if (declarationType.BaseType != null && declarationType.BaseType != typeof(object))
{
uses.Add(GetDeclarationUseFrom(declarationType.BaseType, resolver, null));
}

if (extendedInterfaces != null)
{
var extendedInterfaceFilter = BuildExtendedInterfaceFilter(declarationType, declaration.IsValueType);

foreach (var extendedInterface in extendedInterfaces)
{
uses.Add(GetDeclarationUseFrom(extendedInterface, resolver, null));
if (extendedInterfaceFilter(extendedInterface))
{
uses.Add(GetDeclarationUseFrom(extendedInterface, resolver, null));
}
}
}

Expand All @@ -345,6 +350,25 @@ private static void LoadExtends(AGenericDeclaration<TNode> declaration, IDeclara
}
}

private static Func<Type, bool> BuildExtendedInterfaceFilter(Type declarationType, bool valueType)
{
if ((valueType && ProbeRecordStructType(declarationType)) || (!valueType && ProbeRecordType(declarationType)))
{
// IEquatable must be excluded since it is compiler generated on record type.
return t =>
{
var genericType = t.GetGenericTypeDefinition();
if (genericType != null && genericType == typeof(IEquatable<>))
{
return false;
}
return true;
};
}

return t => true;
}

/// <summary>
/// Load member list.
/// </summary>
Expand Down Expand Up @@ -373,15 +397,20 @@ private void LoadMembers(AGenericDeclaration<TNode> declaration, IDeclarationRes
{
var attributes = LoadCustomAttributes(resolver, property.CustomAttributes);

var propertyType = GetDeclarationUseFrom(property.PropertyType, resolver, null);
memberList.Add(
new PropertyDeclaration(
property.Name,
propertyType,
new ReflectionPropertySyntaxNodeProvider(property, propertyType.SyntaxNodeProvider),
attributes,
property.CanRead,
property.CanWrite));
var compilerAttribute = attributes.FirstOrDefault(attribute => attribute.DeclarationUse.Declaration.FullName == typeof(CompilerGeneratedAttribute).FullName);

if (compilerAttribute == null)
{
var propertyType = GetDeclarationUseFrom(property.PropertyType, resolver, null);
memberList.Add(
new PropertyDeclaration(
property.Name,
propertyType,
new ReflectionPropertySyntaxNodeProvider(property, propertyType.SyntaxNodeProvider),
attributes,
property.CanRead,
property.CanWrite));
}
}

foreach (var method in declaration.GetData<Type>().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class ParameterDeclaration : ADeclaration<ParameterSyntax>, IParameterDec
/// <param name="parameterType">The parameter type use declaration.</param>
/// <param name="syntaxNodeProvider">The declaration syntax node provider.</param>
public ParameterDeclaration(string name, IDeclarationUse<SyntaxNode> parameterType, ISyntaxNodeProvider<ParameterSyntax> syntaxNodeProvider)
: base(string.Empty, name, syntaxNodeProvider, NoUsingDirectives.Instance, null, false)
: base(string.Empty, name, syntaxNodeProvider, NoUsingDirectives.Instance, null, false, false)
{
this.ParameterType = parameterType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public RecordDeclaration(
usingDirectives,
location,
loader,
false)
false,
true)
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public RecordStructDeclaration(
usingDirectives,
location,
loader,
true,
true)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public StructDeclaration(
usingDirectives,
location,
loader,
true)
true,
false)
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class UnknownDeclaration : ADeclaration<SyntaxNode>
/// <param name="nameSpace">The declaration name space.</param>
/// <param name="name">The name of the unknown declaration.</param>
public UnknownDeclaration(string nameSpace, string name)
: base(nameSpace, name, null, NoUsingDirectives.Instance, null, false)
: base(nameSpace, name, null, NoUsingDirectives.Instance, null, false, false)
{
}

Expand All @@ -31,7 +31,7 @@ public UnknownDeclaration(string nameSpace, string name)
/// </summary>
/// <param name="name">The name of the unknown declaration.</param>
public UnknownDeclaration(string name)
: base(string.Empty, name, null, NoUsingDirectives.Instance, null, false)
: base(string.Empty, name, null, NoUsingDirectives.Instance, null, false, false)
{
}

Expand Down
Loading

0 comments on commit 0493322

Please sign in to comment.