| Severity | Error |
| Reported by | Metalama.Extensions.Interceptors |
| Message | The <Site> cannot be intercepted because '<Method>' is a partial method without implementation. A source generator that runs after Metalama could implement it, and the call would then run without the interceptor. |
Cause
The Metalama.Extensions.Interceptors package lets an aspect or a fabric replace the calls to selected methods with calls to another method, called an interceptor.
When a partial method has no implementation in the compilation, the C# compiler removes the calls to it. A source generator that runs after Metalama can still provide the implementation. The call would then run without the interceptor, and the behavior of the program would depend on the generator. To avoid this inconsistency, Metalama reports LAMA1015 for every call to such a method that an interception registration selects. It reports the error before it asks the registration for an interceptor, so returning Skip doesn't prevent it. In the message, <Site> describes the call and <Method> is the partial method.
In the following example, a fabric intercepts the calls to OnPriceChanged, a partial method that has no implementation.
1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Code;
3using Metalama.Framework.Fabrics;
4using System.Linq;
5
6namespace Doc.LAMA1015.Error;
7
8internal class Fabric : ProjectFabric
9{
10 public override void AmendProject( IProjectAmender amender )
11 {
12 amender.SelectTypes()
13 .Where( t => t.Name == "Checkout" )
14 .InterceptMethods(
15 b => b
16 .Type( typeof(Checkout) )
17 .Methods( "OnPriceChanged" )
18 .RedirectToExistingMethod(
19 typeof(PriceChangeHandler).AsINamedType().Methods.OfName( "OnPriceChanged" ).Single() ) );
20 }
21}
22
1using System;
2
3namespace Doc.LAMA1015.Error;
4
5internal static class PriceChangeHandler
6{
7 public static void OnPriceChanged( decimal price ) => Console.WriteLine( $"The price changed to {price}." );
8}
9
10internal static partial class Checkout
11{
12 // The partial method has no implementation, so the compiler omits the call.
13 static partial void OnPriceChanged( decimal price );
14
Error LAMA1015: The call to 'Checkout.OnPriceChanged(decimal)' cannot be intercepted because 'Checkout.OnPriceChanged(decimal)' is a partial method without implementation. A source generator that runs after Metalama could implement it, and the call would then run without the interceptor.
15 public static void Run() => OnPriceChanged( 10m );
16}
17
Resolution
Do one of the following:
- Implement the partial method in the same compilation. In the following example, the method has an implementation, so the call is intercepted.
- Exclude the call from the interception, by selecting another method or by restricting the scope of the registration.
1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Code;
3using Metalama.Framework.Fabrics;
4using System.Linq;
5
6namespace Doc.LAMA1015.Fixed;
7
8internal class Fabric : ProjectFabric
9{
10 public override void AmendProject( IProjectAmender amender )
11 {
12 amender.SelectTypes()
13 .Where( t => t.Name == "Checkout" )
14 .InterceptMethods(
15 b => b
16 .Type( typeof(Checkout) )
17 .Methods( "OnPriceChanged" )
18 .RedirectToExistingMethod(
19 typeof(PriceChangeHandler).AsINamedType().Methods.OfName( "OnPriceChanged" ).Single() ) );
20 }
21}
22
1using System;
2
3namespace Doc.LAMA1015.Fixed;
4
5internal static class PriceChangeHandler
6{
7 public static void OnPriceChanged( decimal price ) => Console.WriteLine( $"The price changed to {price}." );
8}
9
10internal static partial class Checkout
11{
12 // The partial method has an implementation.
13 static partial void OnPriceChanged( decimal price );
14
15 static partial void OnPriceChanged( decimal price ) => Console.WriteLine( price );
16
17 public static void Run() => OnPriceChanged( 10m );
18}
19
1using System;
2
3namespace Doc.LAMA1015.Fixed;
4
5internal static class PriceChangeHandler
6{
7 public static void OnPriceChanged(decimal price) => Console.WriteLine($"The price changed to {price}.");
8}
9
10internal static partial class Checkout
11{
12 // The partial method has an implementation.
13 static partial void OnPriceChanged(decimal price);
14
15 static partial void OnPriceChanged(decimal price) => Console.WriteLine(price);
16
17 public static void Run() => PriceChangeHandler.OnPriceChanged(10m);
18}
19