| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The <Predecessor> cannot add a child aspect of type '<AspectType>' to '<Child>' because <Reason>. |
Cause
Fabrics and aspects can add aspects to other declarations programmatically, typically by selecting declarations with a query and calling its AddAspect method. The added aspects are called child aspects. Like any aspect, a child aspect can define eligibility conditions in its BuildEligibility method.
Metalama reports LAMA0039 when AddAspect selects a declaration that doesn't satisfy the eligibility conditions of the child aspect. The diagnostic is reported on the fabric or on the parent aspect. In the message, <Predecessor> describes the parent fabric or aspect, <AspectType> is the child aspect, <Child> is the ineligible declaration, and <Reason> explains which condition failed.
When you apply an aspect directly with a custom attribute, the same situation is reported as LAMA0037.
In the following example, the Log aspect requires an instance method, but the fabric adds it to all methods of the Calculator class, including a static method.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using Metalama.Framework.Eligibility;
4using System;
5
6namespace Doc.LAMA0039.Error;
7
8public class LogAttribute : OverrideMethodAspect
9{
10 public override void BuildEligibility( IEligibilityBuilder<IMethod> builder )
11 {
12 base.BuildEligibility( builder );
13
14 // The aspect requires an instance method.
15 builder.MustNotBeStatic();
16 }
17
18 public override dynamic? OverrideMethod()
19 {
20 Console.WriteLine( $"Executing {meta.Target.Method}." );
21
22 return meta.Proceed();
23 }
24}
25
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Fabrics;
3
4namespace Doc.LAMA0039.Error;
5
Error LAMA0039: The project fabric 'Fabric' cannot add a child aspect of type 'Log' to 'Calculator.Multiply(int, int)' because 'Calculator.Multiply(int, int)' must not be static.
6internal class Fabric : ProjectFabric
7{
8 public override void AmendProject( IProjectAmender amender )
9 {
10 // Error: AddAspect also selects the static method, which isn't eligible for [Log].
11 amender.SelectTypes()
12 .Where( t => t.Name == "Calculator" )
13 .SelectMany( t => t.Methods )
14 .AddAspect<LogAttribute>();
15 }
16}
17
1namespace Doc.LAMA0039.Error;
2
3internal class Calculator
4{
5 public int Add( int a, int b ) => a + b;
6
7 // The static method isn't eligible for the [Log] aspect.
8 public static int Multiply( int a, int b ) => a * b;
9}
10
Resolution
Depending on your intent, do one of the following:
- Replace AddAspect with AddAspectIfEligible, which silently skips the declarations that aren't eligible. The following example uses this approach.
- Filter the query with Where so that it selects only eligible declarations, for instance
Where( m => !m.IsStatic ). - If you're the author of the child aspect and the condition is too strict, relax it in the aspect's BuildEligibility method.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using Metalama.Framework.Eligibility;
4using System;
5
6namespace Doc.LAMA0039.Fixed;
7
8public class LogAttribute : OverrideMethodAspect
9{
10 public override void BuildEligibility( IEligibilityBuilder<IMethod> builder )
11 {
12 base.BuildEligibility( builder );
13
14 // The aspect requires an instance method.
15 builder.MustNotBeStatic();
16 }
17
18 public override dynamic? OverrideMethod()
19 {
20 Console.WriteLine( $"Executing {meta.Target.Method}." );
21
22 return meta.Proceed();
23 }
24}
25
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Fabrics;
3
4namespace Doc.LAMA0039.Fixed;
5
6internal class Fabric : ProjectFabric
7{
8 public override void AmendProject( IProjectAmender amender )
9 {
10 // Fixed: AddAspectIfEligible skips the methods that aren't eligible for [Log].
11 amender.SelectTypes()
12 .Where( t => t.Name == "Calculator" )
13 .SelectMany( t => t.Methods )
14 .AddAspectIfEligible<LogAttribute>();
15 }
16}
17
1namespace Doc.LAMA0039.Fixed;
2
3internal class Calculator
4{
5 public int Add( int a, int b ) => a + b;
6
7 // The fabric skips this static method.
8 public static int Multiply( int a, int b ) => a * b;
9}
10
1using System;
2
3namespace Doc.LAMA0039.Fixed;
4
5internal class Calculator
6{
7 public int Add(int a, int b)
8 {
9 Console.WriteLine("Executing Calculator.Add(int, int).");
10 return a + b;
11 }
12
13 // The fabric skips this static method.
14 public static int Multiply(int a, int b) => a * b;
15}
16