GetSymbolInfo (). Символ, возвращающий ноль в AttributeSyntax - PullRequest
0 голосов
/ 22 января 2020

У меня есть собственный атрибут, который я использую для тестирования анализатора кода Roslyn, который я пишу:

[AttributeUsage( validOn: AttributeTargets.Class | AttributeTargets.Interface, Inherited = false, AllowMultiple = true )]
public class DummyAttribute : Attribute
{
    public DummyAttribute( string arg1, Type arg2 )
    {
    }

    public int TestField;
}

, который украшает другой тестовый класс:

[Dummy( "", typeof( string ) )]
[Dummy( "test", typeof( int ) )]
[Dummy( "test", typeof( int ) )]
public class J4JLogger<TCalling> : IJ4JLogger<TCalling>
{

Но когда я вызовите GetSymbolInfo () для него с моделью semanti c, в которой она определена:

model.GetSymbolInfo( attrNode ).Symbol

значение Symbol равно нулю.

Странно, что вызов GetSymbolInfo () работает отлично хорошо для классов атрибутов, определенных в базовой библиотеке Net (например, AttributeUsage).

Оба Dummy и J4JLogger определены в одном проекте. Я создаю свой модуль компиляции, анализируя файлы по отдельности (например, J4JLogger анализируется и анализируется отдельно от Dummy), поэтому при анализе J4JLogger нет ссылки на сборку, содержащую как J4JLogger, так и Dummy.

Может ли быть проблема в том, что model на самом деле не содержит класс Dummy, который, я думаю, содержит? Есть ли способ проверить, что в модели semanti c? Нужно ли включать ссылку на сборку, исходный файл которой я анализирую в модели semanti c?

Исправленный логический анализ c

My Исходные логики синтаксического анализа c анализировали каждый файл в синтаксическом дереве независимо от всех его родственных исходных файлов. Правильный способ анализа исходных файлов - по крайней мере, когда они зависят друг от друга - выглядит примерно так:

protected virtual (CompilationUnitSyntax root, SemanticModel model) ParseMultiple( string primaryPath, params string[] auxPaths )
{
    if( !IsValid )
        return (null, null);

    CSharpCompilation compilation;
    SyntaxTree primaryTree;

    var auxFiles = auxPaths == null || auxPaths.Length == 0
        ? new List<string>()
        : auxPaths.Distinct().Where( p => !p.Equals( primaryPath, StringComparison.OrdinalIgnoreCase ) );

    try
    {
        var auxTrees = new List<SyntaxTree>();

        primaryTree = CSharpSyntaxTree.ParseText( File.ReadAllText( primaryPath ) );
        auxTrees.Add( primaryTree );

        foreach( var auxFile in auxFiles )
        {
            var auxTree = CSharpSyntaxTree.ParseText( File.ReadAllText( auxFile ) );
            auxTrees.Add( auxTree );
        }

        compilation = CSharpCompilation.Create( ProjectDocument.AssemblyName )
            .AddReferences( GetReferences().ToArray() )
            .AddSyntaxTrees( auxTrees );
    }
    catch( Exception e )
    {
        Logger.Error<string>( "Configuration failed, exception message was {0}", e.Message );
        return (null, null);
    }

    return (primaryTree.GetCompilationUnitRoot(), compilation.GetSemanticModel( primaryTree ));
}

Небольшая ошибка заключается в том, что AddSyntaxTrees () не выглядит инкрементным; вам нужно добавить все соответствующие синтаксические деревья за один вызов AddSyntaxTrees ().

1 Ответ

0 голосов
/ 22 января 2020

Оказывается, проблема в том, что вы должны включить все исходные файлы, которые ссылаются друг на друга (например, Dummy и J4JLogger в моем случае) в блок компиляции, потому что в противном случае «внутренние» ссылки (например, декорирование J4JLogger с Dummy) не разрешится. Я прокомментировал вопрос с тем, как я переписал мои логи синтаксического анализа c.

...