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.
 
 

98 lines
3.6 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;
// TODO: Support [Source].
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 (Parent is ModuleEntityInfo { IsBuiltIn: true }) yield return Diagnostic.Create(
Descriptors.BuiltInModuleMustNotHaveMethods, Location);
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.DependsOnAttribute");
// TODO: Handle systems with [Source].
// TODO: Validate ObserverEvents.
}
}