Open sandboxFocusImprove this doc

LAMA0270: A template can only be called as a stand-alone statement

Severity Error
Reported by Metalama.Framework
Message The template call '<Call>' cannot be part of another expression or statement. A template can only be called as a stand-alone statement.

Cause

A template can call an auxiliary template, a method marked with [Template]. Metalama doesn't generate a method call: it expands the auxiliary template and inserts the statements it generates at the place of the call. For this reason, the call must be a stand-alone statement, like this.Log();.

Metalama reports LAMA0270 when the call to an auxiliary template is part of another expression or statement, for instance:

  • the expression of a return statement or the initializer of a local variable;
  • an argument of another method call;
  • a part of a for statement, such as its condition;
  • a conditional access, like templates?.Log();
  • the initializer of a field introduced with [Introduce].

Even when the auxiliary template returns a value, you can't use this value in an expression: its return statements become return statements of the target method.

In the following example, the OverrideMethod template returns the result of the Log auxiliary template.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0270.Error;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        // Error: the call to the Log template is part of a return statement.
        Error LAMA0270: The template call 'this.Log()' cannot be part of another expression or statement. A template can only be called as a stand-alone statement.

11        return this.Log();
12    }
13
14    [Template]
15    private dynamic? Log()
16    {
17        Console.WriteLine( $"Executing {meta.Target.Method}." );
18
19        return meta.Proceed();
20    }
21}
22
1namespace Doc.LAMA0270.Error;
2
3internal class Calculator
4{
5    [Log]
6    public int Add( int a, int b ) => a + b;
7}
8

Resolution

Call the auxiliary template as a stand-alone statement. If you need a value, produce it outside of the auxiliary template:

  • Make the auxiliary template void, call it as a statement, and keep the code that produces the value, like meta.Proceed(), in the calling template, as in the following example.
  • If the auxiliary template must end the target method with a value, make it void and call meta.Return(...) in it to generate the return statement.
  • If you only need to compute a compile-time value, use a compile-time method instead of a template.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0270.Fixed;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        // Fixed: the Log template is called as a stand-alone statement.
11        this.Log();
12
13        return meta.Proceed();
14    }
15
16    [Template]
17    private void Log()
18    {
19        Console.WriteLine( $"Executing {meta.Target.Method}." );
20    }
21}
22
Source Code
1namespace Doc.LAMA0270.Fixed;
2


3internal class Calculator
4{
5    [Log]
6    public int Add( int a, int b ) => a + b;
7}
8
Transformed Code
1using System;
2
3namespace Doc.LAMA0270.Fixed;
4
5internal class Calculator
6{
7    [Log]
8    public int Add(int a, int b)
9    {
10        Console.WriteLine("Executing Calculator.Add(int, int).");
11        return a + b;
12    }
13}
14

See also