|
|
@ -1,5 +1,6 @@ |
|
|
|
using System; |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Collections.Generic; |
|
|
|
|
|
|
|
using System.Collections.Immutable; |
|
|
|
using System.Linq; |
|
|
|
using System.Linq; |
|
|
|
using Microsoft.CodeAnalysis; |
|
|
|
using Microsoft.CodeAnalysis; |
|
|
|
|
|
|
|
|
|
|
@ -14,7 +15,11 @@ public abstract class BaseEntityInfo : BaseInfo |
|
|
|
|
|
|
|
|
|
|
|
public List<INamedTypeSymbol> EntitiesToAdd { get; } = new(); |
|
|
|
public List<INamedTypeSymbol> EntitiesToAdd { get; } = new(); |
|
|
|
public List<(INamedTypeSymbol Relation, INamedTypeSymbol Target)> RelationsToAdd { get; } = new(); |
|
|
|
public List<(INamedTypeSymbol Relation, INamedTypeSymbol Target)> RelationsToAdd { get; } = new(); |
|
|
|
public virtual bool HasEntitiesToAdd => (EntitiesToAdd.Count > 0) || (RelationsToAdd.Count > 0); |
|
|
|
public List<(INamedTypeSymbol Component, ImmutableArray<TypedConstant> Arguments)> ComponentsToAdd { get; } = new(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public virtual bool HasEntitiesToAdd => (EntitiesToAdd.Count > 0) |
|
|
|
|
|
|
|
|| (RelationsToAdd.Count > 0) |
|
|
|
|
|
|
|
|| (ComponentsToAdd.Count > 0); |
|
|
|
|
|
|
|
|
|
|
|
public BaseEntityInfo(ISymbol symbol) |
|
|
|
public BaseEntityInfo(ISymbol symbol) |
|
|
|
: base(symbol) |
|
|
|
: base(symbol) |
|
|
@ -41,33 +46,49 @@ public abstract class BaseEntityInfo : BaseInfo |
|
|
|
Descriptors.EntityMustBeInModule, Location); |
|
|
|
Descriptors.EntityMustBeInModule, Location); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Add entities and relationships specified using [Add<...>] attributes. |
|
|
|
|
|
|
|
foreach (var attr in Symbol.GetAttributes()) { |
|
|
|
foreach (var attr in Symbol.GetAttributes()) { |
|
|
|
|
|
|
|
// Add entities and relationships specified using [Add<...>] attributes. |
|
|
|
for (var attrType = attr.AttributeClass; attrType != null; attrType = attrType.BaseType) { |
|
|
|
for (var attrType = attr.AttributeClass; attrType != null; attrType = attrType.BaseType) { |
|
|
|
if (RelevantSymbolReceiver.ToRelevantAttributeName(attrType) != "Add") continue; |
|
|
|
var attrName = RelevantSymbolReceiver.ToRelevantAttributeName(attrType); |
|
|
|
|
|
|
|
if (attrName is "Add" or "Set") { |
|
|
|
|
|
|
|
|
|
|
|
var allTypeArgumentsValid = true; |
|
|
|
var allTypeArgumentsValid = true; |
|
|
|
for (var i = 0; i < attrType.TypeArguments.Length; i++) { |
|
|
|
for (var i = 0; i < attrType.TypeArguments.Length; i++) { |
|
|
|
var arg = attrType.TypeArguments[i]; |
|
|
|
var arg = attrType.TypeArguments[i]; |
|
|
|
var param = attrType.TypeParameters[i]; |
|
|
|
var param = attrType.TypeParameters[i]; |
|
|
|
if (arg is not INamedTypeSymbol) { |
|
|
|
if (arg is not INamedTypeSymbol) { |
|
|
|
yield return Diagnostic.Create( |
|
|
|
yield return Diagnostic.Create( |
|
|
|
Descriptors.InvalidTypeArgument, param.Locations.Single()); |
|
|
|
Descriptors.InvalidTypeArgument, param.Locations.Single()); |
|
|
|
allTypeArgumentsValid = false; |
|
|
|
allTypeArgumentsValid = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// TODO: Make sure entities being added have appropriate attributes as well. |
|
|
|
} |
|
|
|
} |
|
|
|
// TODO: Make sure entities being added have appropriate attributes as well. |
|
|
|
if (!allTypeArgumentsValid) continue; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (allTypeArgumentsValid) { |
|
|
|
switch (attrName) { |
|
|
|
switch (attrType.TypeArguments) { |
|
|
|
case "Add": |
|
|
|
case [ INamedTypeSymbol entity ]: |
|
|
|
switch (attrType.TypeArguments) { |
|
|
|
EntitiesToAdd.Add(entity); |
|
|
|
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"); |
|
|
|
|
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
case [ INamedTypeSymbol relation, INamedTypeSymbol target ]: |
|
|
|
|
|
|
|
RelationsToAdd.Add((relation, target)); |
|
|
|
case "Set": |
|
|
|
|
|
|
|
var component = (INamedTypeSymbol)attrType.TypeArguments.Single(); |
|
|
|
|
|
|
|
var arguments = attr.ConstructorArguments.Single().Values; |
|
|
|
|
|
|
|
// TODO: Verify arguments actually match a constructor. |
|
|
|
|
|
|
|
// Right now this will just error in the generated code. Probably good enough? |
|
|
|
|
|
|
|
ComponentsToAdd.Add((component, arguments)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
default: throw new InvalidOperationException( |
|
|
|
default: throw new InvalidOperationException( |
|
|
|
"Type argument pattern matching failed"); |
|
|
|
"Invalid relevant attribute name"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|