Open sandboxFocusImprove this doc

LAMA0044: An aspect or fabric can't set options outside of its scope

Severity Error
Reported by Metalama.Framework
Message The <Predecessor> cannot set options for '<Child>' because it is not contained in '<Parent>'.

Cause

Aspects and fabrics can set hierarchical options, for instance with the SetOptions method or with a configuration extension method such as ConfigureContracts. They can do this only for declarations within their own scope:

  • A type fabric, or an aspect applied to a type or a member, can set options for its type and the members and nested types of this type.
  • A namespace fabric can set options for its namespace and the types it contains.
  • A project fabric, or an aspect applied to the compilation, can set options for any declaration of the current project.

Metalama reports LAMA0044 when a query selects a declaration outside of this scope, or a declaration of a referenced assembly, and then sets options for it. In the message, <Predecessor> describes the aspect or fabric, <Child> is the declaration for which options are set, and <Parent> is the type or namespace that limits the scope.

The same ID is reported with the message The <Predecessor> cannot add a validator to '<Child>' because it is not contained in '<Parent>'. when an aspect or fabric adds a validator, with the Metalama.Extensions.Validation package, to a declaration outside of its scope. The rule and the resolution are the same.

In the following example, a type fabric tries to configure contracts for the whole namespace of its type.

1using Metalama.Framework.Fabrics;
2using Metalama.Patterns.Contracts;
3
4namespace Doc.LAMA0044.Error;
5
6internal class OrderService
7{
8    public void PlaceOrder( [NotNull] string customerId ) { }
9
    Error LAMA0044: The type fabric on 'Doc.LAMA0044.Error.OrderService' cannot set options for 'Doc.LAMA0044.Error' because it is not contained in 'OrderService'.

10    private class Fabric : TypeFabric
11    {
12        public override void AmendType( ITypeAmender amender )
13        {
14            // Error: a type fabric cannot set options for its containing namespace.
15            amender.Select( t => t.ContainingNamespace )
16                .ConfigureContracts( new ContractOptions { IsInheritable = false } );
17        }
18    }
19}
20

Resolution

Set the options from a fabric whose scope includes the declarations you want to configure:

  • To configure only the current type, call the method on the type fabric's amender directly, without selecting other declarations. The following example shows this fix.
  • To configure a namespace, use a namespace fabric in this namespace.
  • To configure the whole project, use a project fabric.

Source Code
1using Metalama.Framework.Fabrics;
2using Metalama.Patterns.Contracts;

3
4namespace Doc.LAMA0044.Fixed;
5
6internal class OrderService
7{



8    public void PlaceOrder( [NotNull] string customerId ) { }
9




10    private class Fabric : TypeFabric



11    {


12        public override void AmendType( ITypeAmender amender )
13        {
14            // Fixed: the type fabric sets options only for its own type.
15            amender.ConfigureContracts( new ContractOptions { IsInheritable = false } );
16        }
17    }
18}




19
Transformed Code
1using System;
2using Metalama.Framework.Fabrics;
3using Metalama.Patterns.Contracts;
4
5namespace Doc.LAMA0044.Fixed;
6
7
8#pragma warning disable CS0067, CS8618, CS0162, CS0169, CS0414, CA1822, CA1823, IDE0051, IDE0052
9
10internal class OrderService
11{
12    public void PlaceOrder([NotNull] string customerId)
13    {
14        if (customerId == null!)
15        {
16            throw new ArgumentNullException("customerId", "The 'customerId' parameter must not be null.");
17        }
18    }
19
20
21#pragma warning disable CS0067, CS8618, CS0162, CS0169, CS0414, CA1822, CA1823, IDE0051, IDE0052
22
23    private class Fabric : TypeFabric
24    {
25        public override void AmendType(ITypeAmender amender) => throw new System.NotSupportedException("Compile-time-only code cannot be called at run-time.");
26    }
27



28#pragma warning restore CS0067, CS8618, CS0162, CS0169, CS0414, CA1822, CA1823, IDE0051, IDE0052
29
30
31}
32
33#pragma warning restore CS0067, CS8618, CS0162, CS0169, CS0414, CA1822, CA1823, IDE0051, IDE0052
34
35
36

See also