I found the problem: I was filtering out/ignoring IdentifierNameSyntax nodes but leaving in/processing PredefinedTypeSyntax nodes. The string Type is an example of the latter while ConsoleChannel is an example of the former.
This post serves to flesh out a question I asked on the Roslyn gitter.im feed.
I’m writing a code analyzer to gather metadata information about assemblies, namespaces, types, interfaces, methods, fields, etc., in a set of related C# projects. Currently I use Buildalyzer to determine the assemblies needed to compile the source code and the Roslyn C# compiler to compile the source code files into syntax trees from which I extract the symbol information containing the metadata I want.
The current problem I’m running into involves getting symbol information for a type in a C# project referenced by the project I’m compiling. In other words, it’s a type defined in a separate project which is, in Visual Studio terms, a project dependency. Everything compiles fine within Visual Studio. But I can’t “see” the symbol information for the syntax node resulting from compiling the project source code with Roslyn.
Here’s the type I’m trying to see:
using System;
using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Configuration;
namespace J4JSoftware.Logging
{
[Channel("Console")]
public class ConsoleChannel : LogChannel
{
public ConsoleChannel()
{
}
public ConsoleChannel( IConfigurationRoot configRoot, string loggerSection = "Logger")
: base( configRoot, loggerSection )
{
}
public override LoggerConfiguration Configure( LoggerSinkConfiguration sinkConfig, string? outputTemplate = null )
{
return string.IsNullOrEmpty( outputTemplate )
? sinkConfig.Console( restrictedToMinimumLevel : MinimumLevel )
: sinkConfig.Console( restrictedToMinimumLevel : MinimumLevel, outputTemplate : outputTemplate );
}
}
}Again, this file is in a project referenced from the project I’m compiling and analyzing.
Here’s how the ConsoleChannel type is being referred to in the project I’m compiling/analyzing:
using J4JSoftware.Logging;
namespace RoslynNetStandardTestLib
{
[ DummyType( typeof(string) ) ]
[ DummyType( typeof(ConsoleChannel) ) ]
public class AttributedClass
{
}
}The code compiles and both the syntax trees and the SemanticModel are generated without any problems.
However, when I walk down into those two DummyType attribute decorations two different things happen:
- For the first one, referencing typeof(string), I’m able to retrieve the symbol info (which is an INamedTypeSymbol for the type string). The active syntax node has a Kind of PredefinedTypeSyntax.
- But for the second one, referencing typeof(ConsoleChannel), no symbol info is returned; it’s null. The active syntax node has a Kind of TypeOfExpressionSyntax.
Here’s the code I’m using to extract symbol information from a SyntaxNode:
public bool GetSymbol<TSymbol>( SyntaxNode node, out TSymbol? result )
where TSymbol : class, ISymbol
{
result = null;
var symbolInfo = Model.GetSymbolInfo( node );
var rawSymbol = symbolInfo.Symbol ?? Model.GetDeclaredSymbol( node );
if( rawSymbol == null )
return false;
if( rawSymbol is TSymbol retVal )
{
result = retVal;
return true;
}
return false;
}





















