MetalamaCommented examplesCachingStep 2.​ Enforcing eligibility
Open sandboxFocusImprove this doc

Caching example, step 2: adding eligibility

In this example, we will enhance the caching aspect created in the previous example. Although powerful, it has certain limitations. A significant shortcoming we aim to address now is that the aspect generates invalid code when applied to void methods or methods with out or ref parameter, causing user confusion. To prevent this, we will update the aspect to report an error to the user when an invalid method is targeted.

To achieve this, we will implement the BuildEligibility method. This method not only checks for errors but also ensures that such declarations will no longer recommend the aspect in the code refactoring menu of your IDE.

35    public override void BuildEligibility( IEligibilityBuilder<IMethod> builder )
36    {
37        builder.MustSatisfy( m => !m.ReturnType.Is( SpecialType.Void ), m => $"{m} cannot be void" );
38        builder.MustSatisfy(
39            m => !m.Parameters.Any( p => p.RefKind is RefKind.Out or RefKind.Ref ),
40            m => $"{m} cannot have out or ref parameter" );
41    }

An error is now reported when the user tries to apply the aspect to an unsupported method:

1namespace Metalama.Samples.Caching2.Tests.Eligibility;
2
3public class Calculator
4{
5    private int? _value;
6
7    // Eligible.
8    [Cache]
9    public int Add( int a, int b ) => a + b;
10
11    // Ineligible because it is void.
    Error LAMA0037: The aspect 'Cache' cannot be applied to the method 'Calculator.SetValue(int)' because 'Calculator.SetValue(int)' cannot be void.

12    [Cache]
13    public void SetValue( int value ) => this._value = value;
14
15    // Ineligible because it has an out parameter.
    Error LAMA0037: The aspect 'Cache' cannot be applied to the method 'Calculator.TryGetValue(out int?)' because 'Calculator.TryGetValue(out int?)' cannot have out or ref parameter.

16    [Cache]
17    public bool TryGetValue( out int? value )
18    {
19        value = this._value;
20        return value.HasValue;
21    }
22}