Skip to content

Commit

Permalink
Add CommonType Merge
Browse files Browse the repository at this point in the history
-added some BaseType tracking
-added member tracking in Enums for easier combining
-started adding some support for generic types (still need to handle for finding TypeContextContainers)
  • Loading branch information
curin committed Jul 12, 2024
1 parent 04ca8c9 commit 4f79555
Showing 1 changed file with 224 additions and 12 deletions.
236 changes: 224 additions & 12 deletions sources/SilkTouch/Clang/SyntaxContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,34 @@ public SyntaxContext(GeneratedSyntax syntax)
throw new Exception("CompilationUnitSyntax missing");
}
}

foreach(var typeDef in TypeDefinitionContainers)
{
if (typeDef.Value.Count <= 1)
{
continue;
}

for (int i = 0; i < typeDef.Value.Count; i++)
{
List<TypeContextContainer> typesToMerge = [];
for (int j = 1; j < typeDef.Value.Count; j++)
{
if (typeDef.Value[i].Namespace != typeDef.Value[j].Namespace)
{
continue;
}
typesToMerge.Add(typeDef.Value[j]);
typeDef.Value.RemoveAt(j);
j--;
}

if (typesToMerge.Count == 0)
{
continue;
}
}
}
}

Dictionary<string, CompilationContext> Files = [];
Expand All @@ -45,6 +73,119 @@ public SyntaxContext(GeneratedSyntax syntax)

Dictionary<string, List<TypeContextContainer>> TypeDefinitionContainers = [];

private void MergeTypeContainers(TypeContextContainer main, List<TypeContextContainer> typesToMerge)
{
while (main.Type is UnknownTypeContext u)
{
main.Type = typesToMerge[0].Type;
main.Visibility = typesToMerge[0].Visibility;
typesToMerge.RemoveAt(0);
}

SyntaxKind visibility = main.IsPublic ? SyntaxKind.PublicKeyword : SyntaxKind.PrivateKeyword;
bool isStatic = true;

if (main.Type is EnumContext e)
{
if (!e.Node.Modifiers.Any(mod => mod.IsKind(SyntaxKind.StaticKeyword)))
{
isStatic = false;
}

bool emptyBaseType = e.Node.BaseList is null || e.Node.BaseList.Types.Count == 0;

foreach (var merge in typesToMerge)
{
if (visibility != SyntaxKind.PublicKeyword)
{
if (merge.IsPublic)
{
visibility = SyntaxKind.PublicKeyword;
}
else if (visibility != SyntaxKind.ProtectedKeyword && merge.Visibility == SyntaxKind.ProtectedKeyword)
{
visibility = SyntaxKind.ProtectedKeyword;
}
}

if (merge.Type is EnumContext en)
{
if (isStatic && !en.Node.Modifiers.Any(mod => mod.IsKind(SyntaxKind.StaticKeyword)))
{
isStatic = false;
}

foreach (var member in en.Members)
{
if (e.Members.ContainsKey(member.Key))
{
continue;
}
e.Members.Add(member.Key, member.Value);
}

e.Node = e.Node.AddModifiers(en.Node.Modifiers.Where(mod => !mod.IsKind(SyntaxKind.PrivateKeyword) &&
!mod.IsKind(SyntaxKind.ProtectedKeyword) &&
!mod.IsKind(SyntaxKind.PublicKeyword) &&
!e.Node.Modifiers.Any(eMod => mod.IsKind(eMod.Kind()))).ToArray())
.AddAttributeLists(en.Node.AttributeLists.Select(al =>
AttributeList(SeparatedList(al.Attributes.Where(at => !e.Node.AttributeLists
.Any(eAl => eAl.Attributes
.Any(eAt => at.ToString() != eAt.ToString())))))).ToArray());

if (!emptyBaseType)
{
e.Node = e.Node.WithBaseList(en.Node.BaseList);
}
}
else if(merge.Type is not UnknownTypeContext)
{
throw new Exception($"{main.Namespace}.{e.Node.Identifier.Text} is defined multiple times as both an enum and another type");
}
}
}
else if (main.Type is TypeContext t)
{
if (!t.Node.Modifiers.Any(mod => mod.IsKind(SyntaxKind.StaticKeyword)))
{
isStatic = false;
}

foreach (var merge in typesToMerge)
{
if (visibility != SyntaxKind.PublicKeyword)
{
if (merge.IsPublic)
{
visibility = SyntaxKind.PublicKeyword;
}
else if (visibility != SyntaxKind.ProtectedKeyword && merge.Visibility == SyntaxKind.ProtectedKeyword)
{
visibility = SyntaxKind.ProtectedKeyword;
}
}

if (merge.Type is TypeContext ty)
{
t.Node = t.Node.AddModifiers(ty.Node.Modifiers.Where(mod => !mod.IsKind(SyntaxKind.PrivateKeyword) &&
!mod.IsKind(SyntaxKind.ProtectedKeyword) &&
!mod.IsKind(SyntaxKind.PublicKeyword) &&
!t.Node.Modifiers.Any(tMod => mod.IsKind(tMod.Kind()))).ToArray())
.AddAttributeLists(ty.Node.AttributeLists.Select(al =>
AttributeList(SeparatedList(al.Attributes.Where(at => !t.Node.AttributeLists
.Any(tAl => tAl.Attributes
.Any(tAt => at.ToString() != tAt.ToString())))))).ToArray());

}
else if (merge.Type is not UnknownTypeContext)
{
throw new Exception($"{main.Namespace}.{t.Node.Identifier.Text} is defined multiple times as both an type and an enum");
}
}
}

}

private TypeContextContainer GetTypeContainer(TypeSyntax syn, string ns, List<string> usings, TypeContext? currentType, out int pDepth, string parentName = "")
{
pDepth = 0;
Expand Down Expand Up @@ -85,7 +226,7 @@ private TypeContextContainer GetTypeContainer(TypeSyntax syn, string ns, List<st
}
else
{
type = new(string.Empty, new UnknownTypeContext(syn), true);
type = new(string.Empty, new UnknownTypeContext(syn), SyntaxKind.PublicKeyword);
TypeDefinitionContainers.Add(syn.ToString(), new() { type });
}

Expand Down Expand Up @@ -199,13 +340,19 @@ public NamespaceContext(string namesp, BaseNamespaceDeclarationSyntax node, Synt
}
else if (member is EnumDeclarationSyntax e)
{
var en = new TypeContextContainer(namesp, new EnumContext(file, e), e.Modifiers.Any(token => token.IsKind(SyntaxKind.PublicKeyword)));
var en = new TypeContextContainer(namesp, new EnumContext(file, e), e.Modifiers
.Where(token => token.IsKind(SyntaxKind.PublicKeyword) || token.IsKind(SyntaxKind.ProtectedKeyword) || token.IsKind(SyntaxKind.PrivateKeyword))
.Select(token => token.Kind())
.FirstOrDefault(SyntaxKind.PrivateKeyword));
context.AddTypeContextContainer(ref en, e.Identifier.Text);
Types.Add(e.Identifier.Text, en);
}
else if (member is TypeDeclarationSyntax t)
{
var ty = new TypeContextContainer(namesp, new TypeContext(namesp, file, t, context, usings), t.Modifiers.Any(token => token.IsKind(SyntaxKind.PublicKeyword)));
var ty = new TypeContextContainer(namesp, new TypeContext(namesp, file, t, context, usings), t.Modifiers
.Where(token => token.IsKind(SyntaxKind.PublicKeyword) || token.IsKind(SyntaxKind.ProtectedKeyword) || token.IsKind(SyntaxKind.PrivateKeyword))
.Select(token => token.Kind())
.FirstOrDefault(SyntaxKind.PrivateKeyword));
context.AddTypeContextContainer(ref ty, t.Identifier.Text);
Types.Add(t.Identifier.Text, ty);
}
Expand Down Expand Up @@ -242,14 +389,20 @@ public TypeContext(string ns, string file, TypeDeclarationSyntax node, SyntaxCon
if (member is EnumDeclarationSyntax e)
{
string name = $"{(parentName.Length > 0 ? $"{parentName}." : "")}{e.Identifier.Text}";
var en = new TypeContextContainer(ns, new EnumContext(file, e), e.Modifiers.Any(token => token.IsKind(SyntaxKind.PublicKeyword)));
var en = new TypeContextContainer(ns, new EnumContext(file, e), e.Modifiers
.Where(token => token.IsKind(SyntaxKind.PublicKeyword) || token.IsKind(SyntaxKind.ProtectedKeyword) || token.IsKind(SyntaxKind.PrivateKeyword))
.Select(token => token.Kind())
.FirstOrDefault(SyntaxKind.PrivateKeyword));
context.AddTypeContextContainer(ref en, name);
SubTypes.Add(e.Identifier.Text, en);
}
else if (member is TypeDeclarationSyntax t)
{
string name = $"{(parentName.Length > 0 ? $"{parentName}." : "")}{t.Identifier.Text}";
var ty = new TypeContextContainer(ns, new TypeContext(ns, file, t, context, usings, name), t.Modifiers.Any(token => token.IsKind(SyntaxKind.PublicKeyword)));
var ty = new TypeContextContainer(ns, new TypeContext(ns, file, t, context, usings, name), t.Modifiers
.Where(token => token.IsKind(SyntaxKind.PublicKeyword) || token.IsKind(SyntaxKind.ProtectedKeyword) || token.IsKind(SyntaxKind.PrivateKeyword))
.Select(token => token.Kind())
.FirstOrDefault(SyntaxKind.PrivateKeyword));
context.AddTypeContextContainer(ref ty, name);
SubTypes.Add(t.Identifier.Text, ty);
}
Expand Down Expand Up @@ -280,11 +433,20 @@ public TypeContext(string ns, string file, TypeDeclarationSyntax node, SyntaxCon
}
}

if (node.BaseList is not null)
{
foreach (var baseType in node.BaseList.Types)
{
BaseTypes.Add(baseType.Type.ToString(), context.GetTypeContainer(baseType.Type, ns, usings, this, out int _));
}
}

Node = node.WithMembers(List(Array.Empty<MemberDeclarationSyntax>()));
}

public string File;
public TypeDeclarationSyntax Node;
public Dictionary<string, TypeContextContainer> BaseTypes = [];
public Dictionary<string, TypeContextContainer> SubTypes = [];
public Dictionary<string, List<MethodContext>> Methods = [];
public Dictionary<string, FieldContext> Fields = [];
Expand All @@ -302,20 +464,37 @@ public TypeContext(string ns, string file, TypeDeclarationSyntax node, SyntaxCon
}
members.AddRange(Fields.Select(f => f.Value.ToCompletedNode()));
members.AddRange(Properties.Select(p => p.Value.ToCompletedNode()));
return Node.WithMembers(List(members));
return Node.WithMembers(List(members))
.WithBaseList(
BaseList(
SeparatedList(BaseTypes.Select(bType => (BaseTypeSyntax)SimpleBaseType(bType.Value.Type.Syntax)))));
}
}

private class EnumContext : LeafNodeContext<EnumDeclarationSyntax>, IBaseTypeContext
private class EnumContext : IBaseTypeContext
{
public EnumContext(string file, EnumDeclarationSyntax node) : base(node) { File = file; }
public EnumContext(string file, EnumDeclarationSyntax node)
{
File = file;

foreach (var member in node.Members)
{
Members.Add(member.Identifier.Text, new(member));
}

Node = node.WithMembers(SeparatedList(Array.Empty<EnumMemberDeclarationSyntax>()));
}

public EnumDeclarationSyntax Node;

public string File;
public TypeSyntax Syntax => IdentifierName(Node.Identifier.Text);

public Dictionary<string, EnumMemberContext> Members = [];

public MemberDeclarationSyntax? ToCompletedNode()
{
return Node;
return Node.WithMembers(SeparatedList(Members.Select(em => em.Value.Node)));
}
}

Expand All @@ -341,16 +520,28 @@ private class UnknownTypeContext : IBaseTypeContext

private class TypeContextContainer
{
public TypeContextContainer(string ns, IBaseTypeContext ty, bool isPublic)
public TypeContextContainer(string ns, IBaseTypeContext ty, SyntaxKind visibility)
{
Namespace = ns;
Type = ty;
IsPublic = isPublic;
Visibility = visibility;
}

public string Namespace;
public bool IsPublic;
public SyntaxKind Visibility;
public IBaseTypeContext Type;

public bool IsPublic => Visibility == SyntaxKind.PublicKeyword;

public override string ToString()
{
return Type.Syntax.ToString();
}
}

private class EnumMemberContext : LeafNodeContext<EnumMemberDeclarationSyntax>
{
public EnumMemberContext(EnumMemberDeclarationSyntax node) : base(node) { }
}

private class MethodContext : LeafNodeContext<MethodDeclarationSyntax>
Expand All @@ -366,6 +557,27 @@ public MethodContext(string ns, MethodDeclarationSyntax node, SyntaxContext cont
}

public Dictionary<string, TypeContextContainer> Parameters = [];

public override string ToString()
{
return $"{Node.Identifier.Text}({string.Join(',', Parameters.Select(par => $"{par.Value} {par.Key}"))})";
}

public static bool operator ==(MethodContext left, MethodContext right)
{
return left.Node.Identifier.Text == right.Node.Identifier.Text &&
left.Parameters.Values.SequenceEqual(right.Parameters.Values);
}

public static bool operator !=(MethodContext left, MethodContext right)
{
return left.Node.Identifier.Text != right.Node.Identifier.Text ||
!left.Parameters.Values.SequenceEqual(right.Parameters.Values);
}

public override bool Equals(object? obj) => base.Equals(obj);

public override int GetHashCode() => ToString().GetHashCode();
}

private class FieldContext : VariableNodes<FieldDeclarationSyntax>
Expand Down

0 comments on commit 4f79555

Please sign in to comment.