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.
93 lines
3.5 KiB
93 lines
3.5 KiB
using System.Collections.Generic; |
|
using System.Linq; |
|
using gaemstone.SourceGen.Utility; |
|
using Microsoft.CodeAnalysis; |
|
|
|
namespace gaemstone.SourceGen.Structure; |
|
|
|
public class MethodEntityInfo : BaseEntityInfo |
|
{ |
|
public new IMethodSymbol Symbol => (IMethodSymbol)base.Symbol; |
|
|
|
public List<ParameterInfo> Parameters { get; } = new(); |
|
protected override IEnumerable<BaseInfo> GetChildren() => Parameters; |
|
|
|
public bool IsSystem { get; } |
|
public bool IsObserver { get; } |
|
|
|
public bool IsIteratorOnly { get; } |
|
public string? Expression { get; } |
|
public ITypeSymbol[]? ObserverEvents { get; } |
|
|
|
public bool IsStatic => Symbol.IsStatic; |
|
public bool IsGeneric => Symbol.IsGenericMethod; |
|
|
|
public bool HasPhaseSet { get; private set; } |
|
public override bool HasEntitiesToAdd => base.HasEntitiesToAdd || !HasPhaseSet; |
|
|
|
public MethodEntityInfo(ISymbol symbol) |
|
: base(symbol) |
|
{ |
|
IsSystem = Has("System"); |
|
IsObserver = Has("Observer"); |
|
|
|
IsIteratorOnly = (Parameters.Count == 1) && (Parameters[0].Symbol.GetFullName(FullNameStyle.NoGeneric) == "gaemstone.ECS.Iterator"); |
|
Expression = Get("Expression")?.ConstructorArguments.FirstOrDefault().Value as string; |
|
ObserverEvents = Get("Observer")?.AttributeClass!.TypeArguments.ToArray(); |
|
} |
|
|
|
protected override IEnumerable<Diagnostic> ValidateSelf() |
|
{ |
|
foreach (var diag in base.ValidateSelf()) yield return diag; |
|
|
|
if (IsSystem && IsObserver) yield return Diagnostic.Create( |
|
Descriptors.InvalidAttributeCombination, Location, "[System, Observer]"); |
|
|
|
if (Symbol.IsAbstract) yield return Diagnostic.Create( |
|
Descriptors.MethodMustNotBeAbstract, Location); |
|
if (Symbol.IsAsync) yield return Diagnostic.Create( |
|
Descriptors.MethodMustNotBeAsync, Location); |
|
|
|
if (Symbol.Parameters.Length == 0) yield return Diagnostic.Create( |
|
Descriptors.MethodMustHaveParameters, Location); |
|
if (Symbol.IsExtensionMethod) yield return Diagnostic.Create( |
|
Descriptors.MethodMustNotBeExtension, Location); |
|
|
|
if (IsIteratorOnly && (Expression == null)) yield return Diagnostic.Create( |
|
Descriptors.MethodMustHaveExpression, Location); |
|
|
|
if (!IsStatic && Parent is ModuleEntityInfo { IsSingleton: false }) |
|
yield return Diagnostic.Create( |
|
Descriptors.InstanceMethodOnlyValidInSingleton, Location); |
|
|
|
if (IsGeneric) { |
|
if (Symbol.TypeParameters.Length > 1) yield return Diagnostic.Create( |
|
Descriptors.MethodGenericParamAtMostOne, Location); |
|
else { |
|
var param = Symbol.TypeParameters[0]; |
|
if (!SymbolEqualityComparer.Default.Equals(param, Symbol.TypeArguments[0])) |
|
yield return Diagnostic.Create( |
|
Descriptors.MethodGenericParamMustNotBeSubstutited, param.Locations.Single()); |
|
if (param.HasReferenceTypeConstraint || param.HasValueTypeConstraint |
|
|| param.HasUnmanagedTypeConstraint || param.HasNotNullConstraint |
|
|| param.HasConstructorConstraint || (param.ConstraintTypes.Length > 0)) |
|
yield return Diagnostic.Create( |
|
Descriptors.MethodGenericParamMustNotBeConstrained, param.Locations.Single()); |
|
} |
|
} |
|
|
|
// Set TermIndex of parameters. |
|
var termIndex = 1; |
|
foreach (var param in Parameters) |
|
if (param.HasTerm) |
|
param.TermIndex = termIndex++; |
|
|
|
// See if we have any [DependsOn<...>] attributes for this system. |
|
// If not, ModuleGenerator will add [DependsOn<Flecs.Pipeline.OnUpdate>]. |
|
HasPhaseSet = IsSystem && RelationsToAdd.Any(entry => entry.Relation |
|
.GetFullName(FullNameStyle.NoGeneric) == "gaemstone.ECS.DependsOnAttribute"); |
|
|
|
// TODO: Handle systems with [Source]. |
|
// TODO: Validate ObserverEvents. |
|
} |
|
}
|
|
|