SymbolInfo метода расширения - PullRequest
       7

SymbolInfo метода расширения

0 голосов
/ 25 декабря 2018

Мне нужно проанализировать какой-нибудь метод расширения.Например, Enumerable.ToList.

Пример кода для анализа:

var test = @"
using System.Linq;

namespace Test
{
    public class TestType
    {
        void TestMethod()
        {
            var empty = new[] {0};
            var test = empty.ToList();
        }
    }
}";

Диагностика:

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxNodeAction(AnalyzeSymbol, SyntaxKind.InvocationExpression);
}

private static void AnalyzeSymbol(SyntaxNodeAnalysisContext context)
{
    var symbolInfo = context.SemanticModel.GetSymbolInfo(context.Node);
}

Однако symbolInfo.Symbol равно нулю, и кандидатов нет.Если я изменю пример кода следующим образом:

var test = @"
using System.Linq;

namespace Test
{
    public class TestType
    {
        void TestMethod()
        {
            var empty = new[] {0};
            var test = Enumerable.ToList(empty);
        }
    }
}";

, тогда у symbolInfo есть кандидат, но все еще нет Symbol.Как получить информацию о символе вызова метода расширения?

1 Ответ

0 голосов
/ 10 января 2019

Если вы используете вспомогательный класс модульных тестов по умолчанию, который автоматически создается из шаблона проекта «Анализатор с исправлением кода», вы должны знать следующее.

Метод GetSortedDiagnosticsFromDocuments пытаетсязапускать анализаторы даже в случае ошибок компиляции при обработке кода, который вы вводите в качестве входных данных.Конечно, при наличии ошибок компиляции семантическая модель может быть неполной или отсутствующей.

Вы можете изменить этот метод следующим образом:

// old version: no compilation errors detection
var compilationWithAnalyzers = project.GetCompilationAsync().Result.WithAnalyzers(ImmutableArray.Create(analyzer));


// new version: detect the compilation errors
var compilation = project.GetCompilationAsync().Result;             
var compilerErrors = compilation.GetDiagnostics().Where(i => i.Severity == DiagnosticSeverity.Error);

if (compilerErrors.Any())
{
    return compilerErrors.ToArray();
}

var compilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create(analyzer));

Если вы попытаетесь запустить модультестируя этот код и введенную вами строку, вы заметите как минимум 2 ошибки компиляции:

ошибка CS0012: тип "Список <>" определен в сборке, на которую нет ссылок.Необходимо добавить ссылку на сборку 'System.Collections, версия = 4.1.0.0, Culture = нейтральная, PublicKeyToken = b03f5f7f11d50a3a'.

(номер версии может отличаться)

и

ошибка CS5001: Программа не содержит статический метод 'Main', подходящий для точки входа

Вам необходимо устранить эти ошибки, чтобы скомпилировать код, поэтомучто вы можете получить доступ к действительной семантической модели.

  • Измените void TestMethod() на static void Main().В этом нет необходимости, но лучше иметь правильный код без ошибок компилятора.
  • Добавьте ссылку на System.Collections и System.Runtime в ваш динамически сгенерированный проект.Нет удобного способа сделать это в модульных тестах, когда вы используете вспомогательный код из шаблона проекта.Но чтобы проверить это, вы можете изменить метод CreateProject.

По умолчанию настроены 4 дополнительные ссылки.Добавьте недостающие ссылки:

var collectionsReference = MetadataReference.CreateFromFile(typeof(Stack<>).Assembly.Location);
var runtimeReference = MetadataReference.CreateFromFile(typeof(ISet<>).Assembly.Location);

var solution = new AdhocWorkspace()
    .CurrentSolution
    .AddProject(projectId, TestProjectName, TestProjectName, language)
    .AddMetadataReference() //...
    // ...extend the AddMetadataReference chain
    .AddMetadataReference(projectId, collectionsReference)
    .AddMetadataReference(projectId, runtimeReference);

Затем вы сможете скомпилировать код в своих модульных тестах и ​​получить действительную семантическую модель.

Возможно, вы захотите реализовать эту динамическуюссылается на функциональность, например, выставляя объект проекта на лету вызывающей стороне модульного теста.

...