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.
 
 

96 lines
3.2 KiB

using System.Collections.Generic;
using Microsoft.CodeAnalysis;
namespace gaemstone.SourceGen.Structure;
public class TypeEntityInfo : BaseEntityInfo
{
public new INamedTypeSymbol Symbol => (INamedTypeSymbol)base.Symbol;
public List<BaseEntityInfo> Children { get; } = new();
protected override IEnumerable<BaseInfo> GetChildren() => Children;
public bool IsModule { get; }
private bool IsEntity { get; }
public bool IsTag { get; }
public bool IsComponent { get; private set; }
public bool IsSingleton { get; }
public bool IsRelation { get; }
// Built-in entities error if they don't exist.
// When a module is built-in, most attributes become descriptive,
// and don't change or affect the entity they're attached to.
public bool IsBuiltIn { get; protected set; }
public bool IsValueType => Symbol.IsValueType;
public bool IsReferenceType => Symbol.IsReferenceType;
// TODO: Make sure that component has (instance) fields, non-component entity does not have fields.
public TypeEntityInfo(ISymbol symbol)
: base(symbol)
{
IsModule = Has("Module");
IsEntity = Has("Entity");
IsTag = Has("Tag");
IsComponent = Has("Component");
IsSingleton = Has("Singleton");
IsRelation = Has("Relation");
IsBuiltIn = !IsModule && !IsEntity && !IsTag
&& !IsComponent && !IsSingleton && !IsRelation
&& (EntityPath != null);
}
protected override IEnumerable<Diagnostic> ValidateSelf()
{
foreach (var diag in base.ValidateSelf()) yield return diag;
if (Symbol.IsStatic) yield return Diagnostic.Create(
Descriptors.TypeMustNotBeStatic, Location);
if (Symbol.IsAbstract) yield return Diagnostic.Create(
Descriptors.TypeMustNotBeAbstract, Location);
var attributeList = new List<string>();
if (IsModule) attributeList.Add("Module");
if (IsEntity) attributeList.Add("Entity");
if (IsRelation) attributeList.Add("Relation");
if (IsTag) attributeList.Add("Tag");
if (IsComponent) attributeList.Add("Component");
if (IsSingleton) attributeList.Add("Singleton");
switch (attributeList)
{
// No attributes are only valid if [Path] is set.
case [ ]:
if (!IsBuiltIn) yield return Diagnostic.Create(
Descriptors.AttributesRequireTypeOrPath, Location,
$"[{string.Join(", ", attributeList)}]");
break;
// A single attribute is valid.
case [ _ ]:
// The following are valid attribute combinations.
case [ "Module", "Singleton" ]:
case [ "Relation", "Tag" ]:
case [ "Relation", "Component" ]:
break;
default:
yield return Diagnostic.Create(
Descriptors.InvalidAttributeCombination, Location,
$"[{string.Join(", ", attributeList)}]");
if (IsModule) yield return Diagnostic.Create(
Descriptors.ValidModuleAttributesHint, Location);
if (IsRelation) yield return Diagnostic.Create(
Descriptors.ValidRelationAttributesHint, Location);
if (IsSingleton && IsComponent) yield return Diagnostic.Create(
Descriptors.SingletonImpliesComponentHint, Location);
break;
}
// In in a built-in module, this entity is built-in, too.
if (Parent is ModuleEntityInfo { IsBuiltIn: true })
IsBuiltIn = true;
// Singletons are special kinds of components.
if (IsSingleton) IsComponent = true;
}
}