You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
2.8 KiB
78 lines
2.8 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using Microsoft.CodeAnalysis; |
|
|
|
namespace gaemstone.SourceGen.Structure; |
|
|
|
public abstract class BaseEntityInfo : BaseInfo |
|
{ |
|
public new TypeEntityInfo? Parent { get => (TypeEntityInfo?)base.Parent; set => base.Parent = value; } |
|
|
|
public string? Path { get; } |
|
// TODO: Rename this to something sensible, like [Symbol]. |
|
// public bool IsPublic { get; private set; } |
|
// private bool IsPrivate { get; } |
|
|
|
public List<INamedTypeSymbol> EntitiesToAdd { get; } = new(); |
|
public List<(INamedTypeSymbol, INamedTypeSymbol)> RelationsToAdd { get; } = new(); |
|
public bool HasEntitiesToAdd => (EntitiesToAdd.Count > 0) || (RelationsToAdd.Count > 0); |
|
|
|
public BaseEntityInfo(ISymbol symbol) |
|
: base(symbol) |
|
{ |
|
Path = Get("Path")?.ConstructorArguments.FirstOrDefault().Value as string; |
|
|
|
// IsPublic = Symbol.HasAttribute("gaemstone.ECS.PublicAttribute"); |
|
// IsPrivate = Symbol.HasAttribute("gaemstone.ECS.PrivateAttribute"); |
|
} |
|
|
|
protected override IEnumerable<Diagnostic> ValidateSelf() |
|
{ |
|
if (this is ModuleEntityInfo) { |
|
// If this entity is a module, it must not be nested. |
|
if (Symbol.ContainingType != null) yield return Diagnostic.Create( |
|
Descriptors.ModuleMustNotBeNested, Location); |
|
} else { |
|
// Otherwise, it must occur within a module |
|
if (Parent is not ModuleEntityInfo) yield return Diagnostic.Create( |
|
Descriptors.EntityMustBeInModule, Location); |
|
} |
|
|
|
// var moduleIsPublic = (Parent?.IsPublic == true); |
|
// var inheritsPublic = (this is MethodEntityInfo); // Observers and systems don't inherit [Public] from their module. |
|
// IsPublic = IsPublic || (moduleIsPublic && inheritsPublic && !IsPrivate); |
|
|
|
// Add entities and relationships specified using [Add<...>] attributes. |
|
foreach (var attr in Symbol.GetAttributes()) { |
|
for (var attrType = attr.AttributeClass; attrType != null; attrType = attrType.BaseType) { |
|
if (RelevantSymbolReceiver.ToRelevantAttributeName(attrType) != "Add") continue; |
|
|
|
var allTypeArgumentsValid = true; |
|
for (var i = 0; i < attrType.TypeArguments.Length; i++) { |
|
var arg = attrType.TypeArguments[i]; |
|
var param = attrType.TypeParameters[i]; |
|
if (arg is not INamedTypeSymbol) { |
|
yield return Diagnostic.Create( |
|
Descriptors.InvalidTypeArgument, param.Locations.Single()); |
|
allTypeArgumentsValid = false; |
|
} |
|
// TODO: Make sure entities being added have appropriate attributes as well. |
|
} |
|
|
|
if (allTypeArgumentsValid) { |
|
switch (attrType.TypeArguments) { |
|
case [ INamedTypeSymbol entity ]: |
|
EntitiesToAdd.Add(entity); |
|
break; |
|
case [ INamedTypeSymbol relation, INamedTypeSymbol target ]: |
|
RelationsToAdd.Add((relation, target)); |
|
break; |
|
default: throw new InvalidOperationException( |
|
"Type argument pattern matching failed"); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|