Как вывести файл из анализатора кода roslyn?

Я использую roslyn API для написания DiagnosticAnalyzer и CodeFix.

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

Конечно, я всегда могу просто сделать File.WriteAllText(...), но я хотел бы предоставить пользователю больше контроля.

Я также не уверен, как лучше всего запустить создание этого файла, поэтому мои вопросы:

  1. Я не хочу жестко запрограммировать имя файла, как лучше всего предоставить этот параметр пользователю анализатора кода? Файл конфигурации? Если да, то как мне получить к нему доступ? т.е. как узнать каталог?

  2. Если в файле отсутствует одна строка, я хотел бы предложить исправление кода, например «Проект содержит измененные или новые строки, повторно создать строковый файл». Это лучший способ сделать это? Или в визуальную студию можно добавить кнопку или что-то еще?

  3. Я вызываю исполняемый файл devenv.com из командной строки для запуска сборки. Есть ли способ принудительно запустить исправление кода во время сборки или до / после? Или мне придется «вручную» загрузить решение с помощью roslyn и выполнить мое исправление кода?


person Riki    schedule 12.06.2017    source источник
comment
Я только что написал почти такое же расширение, мое предназначено для того, чтобы взять константные строки и поместить их в файл ресурсов для локализации. Я составил список вещей, которые вам нужно знать, чтобы это сделать. Если вам нужен образец кода, я также могу предоставить   -  person johnny 5    schedule 14.06.2017
comment
@ johnny5 Я был бы признателен! Удалось ли вам также переписать строки формата InterpolatedStringExpressionSyntaxinstances? У меня это работает на 90%, иногда просто срабатывает, когда вы указываете такие вещи, как {i:-10}.   -  person Riki    schedule 15.06.2017
comment
Нет, мне просто нужно написать часть в ближайший resx, я работал над локализацией строк   -  person johnny 5    schedule 15.06.2017


Ответы (2)


Я только что завершил проект по этому поводу. Есть несколько вещей, которые вам нужно сделать / знать.

  1. Возможно, вам потребуется переключить переносимую библиотеку классов на библиотеку классов. в противном случае у вас возникнут проблемы с вызовом File.WriteAllText()

Вы можете увидеть, как преобразовать переносимую библиотеку классов в обычную здесь

  1. Это потенциально не сработает при попытке применить все изменения к документу / проекту / решению. При вызове из документа / проекта / решения изменения предварительно рассчитываются и применяются в окне предварительного просмотра. Если вы отмените действие, запускается действие отмены для отмены всех изменений, если вы записываете в файл в течение этого времени и не регистрируете действие отмены, вы не отмените изменения в файле.

Я обнаружил ошибку с roslyn, но вы можете обрабатывать экземпляры, переопределив предварительный просмотр, вы можете увидеть, как это сделать, здесь

  1. И еще одна вещь, которую вам, возможно, нужно знать, это как получить доступ к Решению из анализатора. В настоящее время я написал для этого хак здесь

  2. Как сказал Тамас, вы можете использовать дополнительные файлы, и вы можете увидеть, как это сделать здесь

Вы можете использовать дополнительные файлы, но я знаю, что в той версии, в которой я использую файлы ресурсов, они не помечаются как дополнительные файлы по умолчанию, они являются embeddedResources.
Итак, чтобы моим пользователям не приходилось вручную отмечать ресурс как additonalFiles I написал функцию для извлечения файлов Designer.cs, связанных с файлами ресурсов, из файла csproj с помощью xDoc, вы можете использовать его в качестве примера, если вы решите проанализировать файл csproj:

protected List<string> GetEmbeddedResourceResxDocumentPaths(Project project)
{
    XDocument xmldoc = XDocument.Load(project.FilePath);
    XNamespace msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";

    var resxFiles = new List<string>();
    foreach (var resource in xmldoc.Descendants(msbuild + "EmbeddedResource"))
    {
        string includePath = resource.Attribute("Include").Value;

        var includeExtension = Path.GetExtension(includePath);
        if (0 == string.Compare(includeExtension, RESX_FILE_EXTENSION, StringComparison.OrdinalIgnoreCase))
        {
            var outputTag = resource.Elements(msbuild + LAST_GENERATED_TAG).FirstOrDefault();

            if (null != outputTag)
            {
                resxFiles.Add(outputTag.Value);
            }
        }
    }
    return resxFiles;
}
person johnny 5    schedule 14.06.2017

Для файлов конфигурации вы можете использовать свойство AdditionalFiles msbuild, которое передается анализаторам через контекст. См. здесь.

person Tamas    schedule 12.06.2017