Как динамически переписать AST в плагине resharper?

Запрос:

Я хотел бы иметь возможность написать анализатор, который может предоставить прокси-значение для определенного выражения и инициировать повторный анализ документа.

Мотивация:

Наш код полон тестов ABTests, которые могут находиться либо в развернутом, либо в активном состоянии с группой управления и вариантов. Определение состояния теста выполняется с помощью поиска в базе данных. Для тестов, развернутых с группой управления, любой оператор следующей формы будет иметь значение false:

if(ExperimentService.IsInVariant(ABTest.Test1))
{
}

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

Что делать, если фактический код

if(!ExperimentService.IsInVariant(ABTest.Test1))

или же

if(ExperimentService.IsInVariant(ABTest.Test1) || true)

или же

var val = ..... && (ExperimentService.IsInVariant(ABTest.Test1);
if(val){
  // val is always going to be false if we deployed control.
}

Возможный подход, который я мог бы увидеть, заключается в том, что мы можем написать анализаторы, которые запускаются один раз, и переписать дерево до того, как произойдет фактический анализ IDE (или, ну, просто проанализировать его во второй раз). Они должны срабатывать только один раз и позволять нам заменить одно выражение на другое. Это позволило бы мне поменять местами все эти экспериментальные вызовы на истинные и ложные литералы.

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

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

2 ответа

Решение

Я не думаю, что есть подход, в котором нет компромисса.

ReSharper не поддерживает переписывание AST перед анализом - это просто переписывает текст в файле.

Вы можете написать анализатор, который выделяет код, применив выделение "мертвый код" к содержимому if блок, но, как вы говорите, вам нужно было бы проанализировать код и проанализировать поток управления, чтобы получить его правильно, и я думаю, что это будет очень сложно (ReSharper действительно предоставляет график потока управления, так что вы могли бы его пройти, но это было бы до вас, чтобы А. найти возвращаемое значение IsInVariant и Б. проследить это значение в любых условиях, && или же || заявления, пока вы не найдете подходящий if блок).

Кроме того, вы могли бы отметить IsInVariant метод с ContractAnnotation атрибут, что-то вроде:

[ContractAnnotation("=> false")]
public bool IsInVariant(string identifier)
{
  // whatever...
}

Это скажет анализ ReSharper, что этот метод всегда возвращает false (Вы также можете сказать, что он вернется true/false/null/ не нуль на основе конкретного ввода). Потому что всегда возвращается falseReSharper выделит код серым цветом if заявление или else ветвь, если вы делаете if (!IsInVariant(…)),

Недостатком является то, что ReSharper также добавит предупреждение if заявление, чтобы сказать вам, что выражение всегда возвращает false, Итак, это компромисс, но вы можете изменить серьезность этого предупреждения на Hint, чтобы оно не было таким навязчивым.

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

Вы сказали

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

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

Смотрите этот пример для .tt файлы.

Другие вопросы по тегам