| Severity | Error |
| Reported by | Metalama.Framework |
| Message | Cannot reference '<ReferencedSymbol>' in '<DeclaringSymbol>' because '<ReferencedSymbol>' is compile-time-only but '<DeclaringSymbol>' is <DeclaringScope>. Roslyn types are compile-time-only because the MSBuild property 'MetalamaRoslynIsCompileTimeOnly' is set to true, which is the default when the project references the Metalama.Framework.Sdk package. Consider adding [CompileTime] to '<DeclaringSymbol>', or set <MetalamaRoslynIsCompileTimeOnly>false</MetalamaRoslynIsCompileTimeOnly> in your project file. |
Cause
The Metalama SDK lets compile-time code use the Roslyn API, that is, the types of the Microsoft.CodeAnalysis namespaces, such as ISymbol or SyntaxNode. When the MetalamaRoslynIsCompileTimeOnly MSBuild property is true, Metalama treats all Roslyn types as compile-time-only, like the code model. The Metalama.Framework.Sdk package sets this property to true by default. Without this package, the default is false, and Roslyn types can be used in both run-time and compile-time code.
Metalama reports LAMA0291 when Roslyn types are compile-time-only and a declaration whose scope is run-time or run-time-or-compile-time references one of them outside of a template, typeof, or nameof. It's the Roslyn counterpart of LAMA0117. In the message, <DeclaringSymbol> is the declaration containing the reference, <ReferencedSymbol> is the Roslyn type or member, and <DeclaringScope> is the scope of <DeclaringSymbol>.
In the following example, the project treats Roslyn types as compile-time-only. The helper method IsRoslynSymbol of the Log aspect isn't marked [CompileTime], so it's run-time-or-compile-time, but it uses the Roslyn interface ISymbol.
1using Metalama.Framework.Aspects;
2using Microsoft.CodeAnalysis;
3using System;
4
5namespace Doc.LAMA0291.Error;
6
7public class LogAttribute : OverrideMethodAspect
8{
9 public override dynamic? OverrideMethod()
10 {
11 Console.WriteLine( $"Executing {meta.Target.Method}." );
12
13 return meta.Proceed();
14 }
15
16 // This helper is neither a template nor marked [CompileTime], so it is run-time-or-compile-time.
17 public static bool IsRoslynSymbol( object declaration )
18 {
19 // Error: ISymbol is a Roslyn type, which is compile-time-only in this project.
Error LAMA0291: Cannot reference 'ISymbol' in 'LogAttribute.IsRoslynSymbol(object)' because 'ISymbol' is compile-time-only but 'LogAttribute.IsRoslynSymbol(object)' is run-time-or-compile-time. Roslyn types are compile-time-only because the MSBuild property 'MetalamaRoslynIsCompileTimeOnly' is set to true, which is the default when the project references the Metalama.Framework.Sdk package. Consider adding [CompileTime] to 'LogAttribute.IsRoslynSymbol(object)', or set <MetalamaRoslynIsCompileTimeOnly>false</MetalamaRoslynIsCompileTimeOnly> in your project file.
20 return declaration is ISymbol;
21 }
22}
23
1namespace Doc.LAMA0291.Error;
2
3internal class Calculator
4{
5 [Log]
6 public int Add( int a, int b ) => a + b;
7}
8
Resolution
Depending on your intent, do one of the following:
- If the code is meant to run at compile time, add [CompileTime] to the declaration or to its containing type. The following example adds
[CompileTime]to the helper method. - If the project uses Roslyn in run-time code, for instance because it's a tool built on Roslyn, set
<MetalamaRoslynIsCompileTimeOnly>false</MetalamaRoslynIsCompileTimeOnly>in aPropertyGroupof the project file. Roslyn types then become run-time-or-compile-time.
1using Metalama.Framework.Aspects;
2using Microsoft.CodeAnalysis;
3using System;
4
5namespace Doc.LAMA0291.Fixed;
6
7public class LogAttribute : OverrideMethodAspect
8{
9 public override dynamic? OverrideMethod()
10 {
11 Console.WriteLine( $"Executing {meta.Target.Method}." );
12
13 return meta.Proceed();
14 }
15
16 // Fixed: the helper is marked [CompileTime], so it can use Roslyn types.
17 [CompileTime]
18 public static bool IsRoslynSymbol( object declaration )
19 {
20 return declaration is ISymbol;
21 }
22}
23
1namespace Doc.LAMA0291.Fixed;
2
3internal class Calculator
4{
5 [Log]
6 public int Add( int a, int b ) => a + b;
7}
8
1using System;
2
3namespace Doc.LAMA0291.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