Не можете специально пройтись по синтаксическому дереву?

Я пытаюсь реализовать инициализатор Diagnostic Analyzer for Collection и соответствующий поставщик исправлений кода.

Неправильный код:

var sampleList= new List<string>();
sampleList.Add("");
sampleList.Add("");

После исправления кода:

var sampleList= new List<string>(){"", ""};

Но я застрял в этой проблеме: как только я получаю узел для LocalDeclarationStatement, я не знаю, существует ли способ получить следующий соседний узел от родителя.

Синтаксическое дерево

На приведенном выше рисунке мне нужны как ExpressionStatement после анализа LocalDeclarationStatement

ТРЕБОВАНИЯ к анализатору

  1. Определите LocalDeclarationStatement, коллекцию, которая уже инициализирована, но не содержит CollectionInitializerExpression
  2. Найдите, есть ли в самой следующей строке оператор Expression, использующий метод Add для той же коллекции.

ТРЕБОВАНИЕ для исправления кода

  1. Предоставьте синтаксис инициализатора коллекции для смежных выражений, использующих метод Add в коллекции.
  2. Следует избегать любого другого прерывистого использования метода Add в коллекции.

person Jerric Lyns John    schedule 20.10.2014    source источник


Ответы (2)


Вы можете сделать что-то вроде:

var declarationStatement = ...;
var block = (BlockSyntax)declarationStatement.Parent;
var index = block.Statements.IndexOf(declarationStatement);
var nextStatement = block.Statements[index + 1];
person Jason Malinowski    schedule 20.10.2014
comment
Это отлично работает! Я правда ценю это. - person Jerric Lyns John; 21.10.2014
comment
Как удалить дополнительные строки кода (соседние вызовы Add), которые были заменены синтаксисом инициализатора коллекции с использованием того же поставщика CodeFix. Я смог предоставить исправление для инициализатора коллекции, но не смог удалить другие последовательные строки вызова Add. - person Jerric Lyns John; 21.10.2014
comment
@JerricLynsJohn Вы пробовали метод расширения RemoveNode? - person svick; 21.10.2014
comment
@svick Да, но, похоже, это не повлияло на корень. Я не уверен, правильно ли я это сделал. root.RemoveNode(expression, SyntaxRemoveOptions.KeepNoTrivia) - person Jerric Lyns John; 21.10.2014
comment
@JerricLynsJohn Как и все в Roslyn, RemoveNode не изменяет исходное дерево, а возвращает новое. Итак, вам нужно что-то вроде root = root.RemoveNode(…);. - person svick; 21.10.2014
comment
@svick Я пробовал это, это определенно работает для удаления одного узла, но если бы я хотел удалить больше и изменить некоторые, то у меня было бы чертовски много времени, пытаясь понять это. я я разместил это как еще один вопрос здесь. - person Jerric Lyns John; 22.10.2014

Разве вам не нужно просто превратить бетонный блок в список и проверить?

var nodes = yourSyntaxTree.DescentNodes().ToList();

for(var i = 0; i < nodes.Count; i++){
  var localDeclarationStatement = nodes[i] as LocalDeclarationStatement;
  if(localDeclarationStatement==null && i + 1 >= nodes.Length)
      continue;

  var expressionStatement = nodes[i+1] as ExpressionStatement;
  if(expressionStatement==null)
     continue;

  // there you have it.
}
person Erti-Chris Eelmaa    schedule 20.10.2014