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
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; |
|
} |
|
}
|
|
|