Ошибка полного метаданных пространства имен с Roslyn

Я пытаюсь создать анализатор кода, который проверяет полностью квалифицированные операторы использования. Эта ссылка была невероятно полезной и послужила основой для моего решения (Как мне получить полное пространство имен из директивы using в Roslyn?), но я сталкиваюсь с проблемой, когда пытаюсь получить доступ к расположению символа для использования директива. Мой код выглядит так:

    private static void AnalyzeModel(SemanticModelAnalysisContext semanticModelAnalysisContext)
    {
        var semanticModel = semanticModelAnalysisContext.SemanticModel;
        var root = semanticModel.SyntaxTree.GetRoot();

        // compare each using statement's name with its fully qualified name
        foreach (var usingDirective in root.DescendantNodes().OfType<UsingDirectiveSyntax>())
        {
            var symbol = semanticModel.GetSymbolInfo(usingDirective.Name).Symbol;
            var fullyQualifiedName = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);

            if (fullyQualifiedName.Contains(GlobalTag))
            {
                fullyQualifiedName = fullyQualifiedName.Substring(GlobalTag.Length);
            }

            if (usingDirective.Name.ToString() != fullyQualifiedName)
            {
                // for each name that is not fully qualified, produce a diagnostic.
                var diagnostic = Diagnostic.Create(Rule, symbol.Locations[0], symbol.Name);
                semanticModelAnalysisContext.ReportDiagnostic(diagnostic);
            }
        }
    }

Проблема в том, что symbol.Locations[0] содержит только элементы в метаданных, а не элементы в исходном коде. Это приводит к следующей ошибке:

Assert.IsTrue failed. Test base does not currently handle diagnostics in metadata locations.

Мой источник в моих модульных тестах выглядит так:

private const string incorrectSourceCode = @" namespace System { using IO; using Threading; }";

Почему в symbol.Locations нет элементов, которые есть в исходном коде? Есть ли другое место, где я могу получить это местоположение? Я пытался использовать symbol.ContainingSymbol.Locations[0] или symbol.ContainingNamespace.Locations[0], но они не относятся к конкретному использованию, которое меня интересует. Я рвал на себе волосы в течение нескольких часов, и некоторая ясность была бы очень признательна.

Заранее спасибо!


person CynicalPassion63    schedule 25.08.2017    source источник


Ответы (1)


Symbol содержит MetadateLocation, поэтому, если вы хотите увидеть SourceLocation, просто извлеките его из соответствующего SyntaxNode:

var diagnostic = Diagnostic.Create(Rule, usingDirective.Name.GetLocation(), symbol.Name)

вместо

var diagnostic = Diagnostic.Create(Rule, symbol.Locations[0], symbol.Name)
person George Alexandria    schedule 26.08.2017
comment
Это решение сработало как шарм. Большое спасибо за то, что поделились своими знаниями, вы добрая душа. :) - person CynicalPassion63; 28.08.2017