[英]How can I have all references of a method in Roslyn (method is called by other classes)?
Thanks to Roslyn , having access to.Net compiler, in our project Gcop we need to have list of references where are calling a method.感谢Roslyn ,可以访问 .Net 编译器,在我们的项目Gcop中,我们需要有调用方法的引用列表。
VS IDE shows the reference places very suitable like this: VS IDE 显示参考位置非常适合这样:
Actually I want to understand which class/name space and even assembly is calling my method by Roslyn C# syntax.实际上我想了解哪个类/名称空间甚至程序集正在通过Roslyn C# 语法调用我的方法。
Currently I have access to MethodSymbol here:目前我可以在这里访问 MethodSymbol:
var methodSymbol = semanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol;
what should I write to get access to references of this method?我应该写什么来访问这个方法的引用?
//added recently for double check //最近添加以进行双重检查
var solutionPath = Utilities.DteExtensions.SolutionFullPath;
var msWorkspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
var result = new List<ReferenceLocation>();
var refrences = SymbolFinder.FindReferencesAsync(methodSymbol, solution).Result;
foreach (var refernc in refrences)
{
foreach (var location in refernc.Locations)
{
result.Add(location);
}
}
///???????? why the result is empty ?
您正在寻找SymbolFinder
类的FindReferencesAsync()
方法。
I tested this approach but is not quick , and can not find some syntax 我测试了这种方法,但是速度并不快,并且找不到一些语法
protected override void Analyze(SyntaxNodeAnalysisContext context)
{
NodeToAnalyze = context.Node;
Method = context.Node as MethodDeclarationSyntax;
// only public method should be checked
if (!IsModifiersValid) return;
var methodSymbol = context.SemanticModel.GetDeclaredSymbol(Method) as IMethodSymbol;
var solutionPath = Utilities.DteExtensions.SolutionFullPath;
var msWorkspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
// looking in all projects inside of one solution
var allDocumentsInEntireSolution = solution.Projects.SelectMany(it => it.Documents);
//skip rule when in entire solution we have web form project
if (allDocumentsInEntireSolution.Any(x => x.Name == "Default.aspx.cs")) return;
//Looking for all references
var refrencesFound = FindAllMethodReferences(Method.GetName(), solution);
if (refrencesFound.Count() ==0)
ReportDiagnostic(context, Method);
else
{
var xyx = refrencesFound.Count();
}
}
IEnumerable<ReferenceLocation> FindAllMethodReferences(string methodName, Solution solution)
{
IMethodSymbol methodSymbol = null;
bool found = false;
foreach (var project in solution.Projects)
{
foreach (var document in project.Documents)
{
var model = document.GetSemanticModelAsync().Result;
var methodInvocation = document.GetSyntaxRootAsync().Result;
try
{
var nodes = methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>().Where(x => x.Expression.ToString().Contains(methodName));
foreach (var node in nodes)
{
if (node == null) continue;
var member = node?.Expression as MemberAccessExpressionSyntax;
if (member == null)
continue;
var name = member?.Name?.ToString();
if (name.IsEmpty()) continue;
if (name != methodName) continue;
methodSymbol = model.GetSymbolInfo(node).Symbol as IMethodSymbol;
found = true;
break;
}
}
catch (Exception exp)
{
// Swallow the exception of type cast.
// Could be avoided by a better filtering on above linq.
continue;
}
}
if (found) break;
}
if (found == false) return Enumerable.Empty<ReferenceLocation>();
if (methodSymbol == null) return Enumerable.Empty<ReferenceLocation>();
var result = new List<ReferenceLocation>();
var refrences = SymbolFinder.FindReferencesAsync(methodSymbol, solution).Result;
foreach (var refernc in refrences)
{
foreach (var location in refernc.Locations)
{
result.Add(location);
}
}
return result;
}
I prefer to change following to make it work:我更喜欢更改以下内容以使其工作:
var nodes = methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>()
.Where(x => x.Expression.ToString().Contains(methodName));
To:到:
var nodes = new List<InvocationExpressionSyntax>();
foreach (var methodInvocationExpression in methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>())
{
if(methodInvocationExpression.DescendantNodes().OfType<MemberAccessExpressionSyntax>().Any(x => x.Name.Identifier.ValueText == methodName))
{
nodes.Add(methodInvocationExpression);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.