Как я могу сделать мой синтаксис диагностики кода node действием закрытых файлов?

Я создаю набор диагностических кодов с использованием Roslyn (в VS2015 Preview). В идеале, я бы хотел, чтобы любые ошибки, которые они производят, действовали как постоянные ошибки, так же, как если бы я нарушал нормальное языковое правило.

Есть множество вариантов, но мне трудно заставить любой из них работать последовательно. Мне удалось реализовать элементарное синтаксическое действие node, т.е. Зарегистрированное в

context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.InvocationExpression);

в методе Initialize моего диагностического класса. И вот, когда я открываю файл, который нарушает эту диагностику (при запуске проекта VSIX), VS2015 показывает ошибку:

  • Красная кривая под правом битом кода
  • Красный блок в поле
  • Ошибка в списке ошибок

Однако при закрытии файла ошибка исчезает.

Я попытался использовать context.RegisterCompilationEndAction, но это имеет две проблемы:

  • Кажется, огонь непоследовательно. Обычно, когда я открываю решение, оно срабатывает, но не всегда. Он не срабатывает при чистом/восстановлении, что кажется странным.
  • Хотя диагностика, созданная непосредственно в методе метода анализа, для реализации диагностики я использую посетителя, например, это может быть неуместным:

    private static void AnalyzeEndCompilation(CompilationEndAnalysisContext context)
    {
        foreach (var tree in context.Compilation.SyntaxTrees)
        {
            var visitor = new ReportingVisitor(context.Compilation.GetSemanticModel(tree));
            visitor.Visit(tree.GetRoot());
            foreach (var diagnostic in visitor.Diagnostics)
            {
                context.ReportDiagnostic(diagnostic);
            }
        }
    }
    

    Я знаю, что диагностика создается - точка останова в строке ReportDiagnostic попадает несколько раз, но я не вижу ничего в списке ошибок. (В то время как аналогичный вызов ReportDiagnostic в начале метода или один для дерева синтаксиса с указанием пути к файлу отображается.)

Что я здесь делаю неправильно? Первый подход (синтаксис node action) был бы идеальным, если это осуществимо - он дает мне именно тот контекст, в котором я нуждаюсь. Есть ли какой-либо параметр в свойствах проекта, который мне нужно сделать, чтобы компилятор использовал это для компиляции "полного проекта", а также просто интерактивную обработку "в среде IDE"? Возможно, это всего лишь часть интеграции Roslyn, которая еще не закончена?

(Я мог бы включить полный код для класса, если бы это было полезно - в этом случае я подозреваю, что это будет больше шума, чем сигнал.)

Ответ 1

В случае проблем с закрытыми файлами мы намерены сообщать о всех диагностиках из открытых или закрытых файлов. В предпросмотре есть опция пользователя в меню "Инструменты\Параметры\Текстовый редактор\С#\Продвинутый", который вы можете включить, чтобы включить диагностику в закрытые файлы. Мы надеемся сделать это по умолчанию до выпуска VS 2015. Однако обратите внимание, что этот параметр применим только к анализу в VS. Если ваш анализатор передается компилятору (добавив анализатор в Обозреватель решений или добавив ссылку на пакет NuGet в пакет с анализатором, а не установку VSIX в Visual Studio), компилятор сообщит о всех диагностических показаниях, когда пользователь строит, независимо от того, открыты ли файлы или нет.

Для второй проблемы с RegisterCompilationEndedAnalyzer она не надежно вызывается внутри Visual Studio в VS 2015 Preview. Это связано с тем, что мы делаем некоторые оптимизации, чтобы избежать повторного анализа всего для "локальных" изменений внутри тел метода. По аналогичным причинам мы в настоящее время не сообщаем об ошибках, сообщаемых с местоположениями в телах методов. Мы только что изменили это так, чтобы VS выдержал полный повторный анализ после более длительной задержки, и поэтому RegisterCompilationEndedAnalyzer следует надежно называть в будущих сборках, и мы сообщим о ошибках независимо от местоположения.

Однако для вашего случая правильная вещь - остаться с SyntaxNodeAnalyzer, переключить опцию VS, чтобы включить диагностику в закрытых файлах, и прикрепить свою диагностику к параметрам компиляции проекта.

Надеюсь, это поможет!