2016-11-24 6 views
1

Я пытаюсь написать правило анализа кода с roslyn.Проверьте, включен ли аргумент объекта ObjectCreationExpressionSyntax в блок catch try или нет.

В принципе, я должен проверить, не создается ли каждый из аргументов, который создается Microsoft.Practices.Prism.Commands.DelegateCommand(), в try catch или нет.

Основная идея собрать все ObjectCreationExpressionSyntax объектов DelegateCommand класса и проверить аргумент каждого конструктора, если первый StatementSyntax является TryStatementSyntax или нет.

Помогите мне с получением всего StatementSyntax от ArgumentSyntax? Или, может быть, у вас есть другой подход?

public IEnumerable<IdentifierInfo> Collect(SyntaxNode rootNode, SemanticModel semanticModel) 
{ 
    ObjectCreationExpressionSyntax[] objCreation = rootNode 
                .DescendantNodes() 
                .OfType<ObjectCreationExpressionSyntax>() 
                .Where(c=>(c.Type as IdentifierNameSyntax)?.Identifier.Value.ToString() == "DelegateCommand") 
                .ToArray(); 

    foreach (var obj in objCreation) 
    { 
     var args = obj.ArgumentList.Arguments; 

     foreach (ArgumentSyntax arg in args) 
     { 
      var expession = arg.Expression; 
      var symbol = semanticModel.GetSymbolInfo(expession).Symbol as IMethodSymbol; 
     } 
    } 
} 

Ниже вы можете найти то, что я на самом деле компиляции для поиска через:

public class Program 
{ 
    public delegate void MyDelegate(); 
    public static void DelegateMethod() { try { } catch { } } 
    public static void Main(string[] args) 
    { 
     DelegateCommand del1 = new DelegateCommand(() => {try{}catch{}}); 
     DelegateCommand del2 = new DelegateCommand(new Action(() => { })); 
     DelegateCommand del3 = new DelegateCommand(DelegateMethod); 
     var barInit = (Action)(DelegateMethod); 
     DelegateCommand del4 = new DelegateCommand(barInit); 
     ICommand test; 
     test = new Microsoft.Practices.Prism.Commands.DelegateCommand(() => { }); 
    } 
} 
+0

Это PRISM 5 или выше? Тогда вы также можете обработать вариант 'DelegateCommand.FromAsync()', не так ли? – Ties

ответ

2

Вы начинаете в хорошем смысле, но справиться с этим полностью, его необходимо проведение дополнительной работы.

Давайте посмотрим, в вашем примере, что мы имеем

LINQ result (скриншот от LINQ debugging feature из OzCode)

Вот что я написал это

var argsExpr = objCreation.Select(o => o.ArgumentList.Arguments.First()) 

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

У вас есть два способа справиться с этим.

  1. метод записи, которые получают SyntaxNode и в соответствии с его типом, проверьте, если первое утверждение является попытка \ Отчет поймать
  2. Написать SyntaxWalker и посетить соответствующие методы, и проверьте, если первое утверждение является попытка \ задвижка заявление

Например, чтобы обрабатывать первый случай, который ParenthesizedLambdaExpressionSyntax вам нужно написать что-то вроде этого (или самостоятельно, либо перекрывая соответствующий Visit метод SyntaxWalker)

public static bool IsTryStatement(ParenthesizedLambdaExpressionSyntax node) 
{ 
    return ((BlockSyntax) node.Body).Statements.First() is TryStatementSyntax; 
} 

Это всего лишь пример. В вашем реальном коде вам нужно обрабатывать все случаи.

Для IdentifierNameSyntax вам нужно, чтобы получить символ метода первого:

semanticModel.GetSymbolInfo(identifier).Symbol 

Тогда вам нужно получить узел синтаксиса от DeclaringSyntaxReferences и использовать срок, или вы можете использовать location символа или любым другим способом (ConstructFrom возможно).