| 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.
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
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