Как динамически переписать 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
/ не нуль на основе конкретного ввода). Потому что всегда возвращается false
ReSharper выделит код серым цветом if
заявление или else
ветвь, если вы делаете if (!IsInVariant(…))
,
Недостатком является то, что ReSharper также добавит предупреждение if
заявление, чтобы сказать вам, что выражение всегда возвращает false
, Итак, это компромисс, но вы можете изменить серьезность этого предупреждения на Hint, чтобы оно не было таким навязчивым.
Этого недостаточно для реального вознаграждения, но одно из решений, которое может быть применено в документации разработчика, - это создание собственного языка и расширение основных правил.
Вы сказали
Я пытаюсь предоставить инструментарий, чтобы с этим легче было справляться во время разработки, используя его в этом сценарии.
Выделение соответствующих частей может быть сделано путем изменения правил подсветки синтаксиса.
Смотрите этот пример для .tt
файлы.