File paths in a Roslyn analyzer or source generator

 
 
  • Gérald Barré

In Roslyn, a SyntaxTree represents the content of a source file. To determine which source file created a given SyntaxTree, use the FilePath property, which returns the path on disk. However, the disk path may not always be what you need.

  • On CI, you should use reproducible builds to get deterministic paths (ContinuousIntegrationBuild=true and <SourceRoot>). In this case, the file paths used for the [CallerFilePathAttribute] and PDB are deterministic paths that do not correspond to the disk path. Instead, it should be something starting with /_/.
  • You can use the #line preprocessor directive to change the file path of the next line. This directive is often used by code generators. For instance, when a XAML file generates a C# file, the C# files contain #line directives to map the original XAML node.
C#
SyntaxTree syntaxTree = ...;

// Get the actual file path on disk
syntaxTree.FilePath;

// Get the mapped file path
_ = syntaxTree.GetLocation().GetMappedLineSpan().Path;

Another useful type is SourceReferenceResolver, accessible from a Compilation instance via compilation.Options.SourceReferenceResolver. Note that it may be null.

C#
static string GetDisplayPath(this SyntaxTree tree, TextSpan span, SourceReferenceResolver? resolver)
{
    var mappedSpan = tree.GetMappedLineSpan(span);
    if (resolver == null || mappedSpan.Path.Length == 0)
        return mappedSpan.Path;

    return resolver.NormalizePath(mappedSpan.Path, baseFilePath: mappedSpan.HasMappedPath ? tree.FilePath : null) ?? mappedSpan.Path;
}

If you have an IOperation, you can get the path through the Syntax property.

C#
IOperation operation = ...;
_ = operation.Syntax.SyntaxTree.FilePath;

If you have an ISymbol, you can get the paths through the Locations property.

C#
ISymbol operation = ...;
foreach (var location in symbol.Locations)
{
    _ = location.SourceTree?.FilePath;
}

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?