2016-02-17 3 views
1

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

Я начинаю с MethodDeclarationSyntax и получаю от этого символ. Затем я использую метод FindCallersAsync в SymbolFinder, но он возвращает пустую коллекцию, даже когда я делаю вызов рассматриваемого метода где-то в сборке. См. Код ниже.

protected override void Analyze(SyntaxNodeAnalysisContext context) 
{ 
    NodeToAnalyze = context.Node; 
    var methodDeclaration = NodeToAnalyze as MethodDeclarationSyntax; 

    if (methodDeclaration == null) 
     return; 

    var methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration) as ISymbol; 

    if (methodSymbol.DeclaredAccessibility != Accessibility.Internal) 
     return; 

    var solutionPath = GetSolutionPath(); 

    var msWorkspace = MSBuildWorkspace.Create(); 
    var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result; 

    var callers = SymbolFinder.FindCallersAsync(symbol, solution).Result; // Returns empty collection. 

    ... 
} 

Я видел подобный код here, но в этом примере символ метода получен с помощью GetSymbolInfo на условиях InvocationExpressionSyntax:

//Get the syntax node for the first invocation to M() 
var methodInvocation = doc.GetSyntaxRootAsync().Result.DescendantNodes().OfType<InvocationExpressionSyntax>().First(); 
var methodSymbol = model.GetSymbolInfo(methodInvocation).Symbol; 
//Finds all references to M() 
var referencesToM = SymbolFinder.FindReferencesAsync(methodSymbol, doc.Project.Solution).Result; 

Однако, в моем случае, мне нужно найти вызовы (если любой) из декларации. Если я сначала вызываю вызов и передаю символ от GetSymbolInfo, вызовы метода возвращаются правильно - поэтому проблема, похоже, связана с параметром symbol, а не solution.

Поскольку я пытаюсь получить основной символ декларации, я не могу использовать GetSymbolInfo, но вместо этого используйте GetDeclaredSymbol (как предложено here).

Мое понимание от this статья в том, что символы, возвращенные с GetDeclaredSymbol и GetSymbolInfo, должны быть одинаковыми. Однако простое сравнение с использованием Equals возвращает false.

Есть ли у кого-нибудь представление о том, какая разница между двумя возвращаемыми символами и как я могу получить «правильный», который работает? Или, может быть, есть лучший подход? Все мои исследования, похоже, указывают на FindCallersAsync, но я просто не могу заставить его работать.

ответ

3

Мое понимание из этой статьи состоит в том, что символы, возвращаемые из GetDeclaredSymbol и GetSymbolInfo, должны быть одинаковыми. Однако простое сравнение с использованием Equals возвращает false.

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

Принципиально использование MSBuildWorkspace в анализаторе не поддерживается. Полностью. Не делай этого. Это не только действительно медленный, но также имеет различные проблемы с правильностью, особенно если вы используете анализатор в Visual Studio. Если ваша цель - найти неиспользуемые методы в любом месте решения, это то, что мы действительно не поддерживаем в качестве анализатора, поскольку это связано с кросс-проектным анализом.

+2

Для «внутренних» методов одним из подходов было бы зарегистрироваться для анализа символов метода, когда они определены, и выражений вызова, и отслеживать все символы, которые определены, но не вызываются. (Технически, вызывается недостаточно, поскольку они могут появляться в 'nameof', как часть создания делегата и т. Д.). –

Смежные вопросы