Open sandboxFocusImprove this doc

LAMA0039: A child aspect is added to an ineligible declaration

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
Source Code
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
Transformed Code
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

See also