我想使用 Roslyn 创建 Visual Studio扩展(VSIX)。此扩展应查找所有调用,然后查找其定义以分析在其上定义的属性。该方法的定义可以是解决方案中的任何位置。
我的第一堂课是这样的:
namespace MainProject
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(BusinessProject.Calc.AddNumbers(5, 8));
}
}
}
我的第二堂课如下:
namespace BusinessProject
{
public class Calc
{
[CustomAttr("Do something")]
public static long AddNumbers(int a, int b)
{
return a + b;
}
}
}
在上面的示例中,在程序类中,我调用了 AddNumbers 方法。我想1)分析代码,2)找到这个调用,3)获取类 Calc 中的引用方法的所有属性,4)进程属性参数,5)然后发出警告/错误如果需要的话。 我可以通过 RegisterCodeBlockAction 分析当前类以查找所有调用,但我不能做的是访问整个解决方案以查找调用的定义,然后访问引用的属性。
如何在 RegiserCodeBlockAction 中访问整个解决方案?
答案 0 :(得分:2)
你说的是错误的方法。
您实际上希望分析器在每个方法调用上运行,而不是每个代码块都运行
因此,您应该致电RegisterSyntaxNodeAction
,然后通过SyntaxKind.InvocationExpression
。
然后它将使用InvocationExpressionSyntax
来呼叫您,其中包含您需要的所有信息(主要在语义模型中)。
答案 1 :(得分:1)
正如@SLaks在评论中提到的,通过使用 SemanticModel.Compilation.SyntaxTrees ,我们可以访问解决方案中的所有源代码。我找到了方法及其参数。但是这有一个问题,您无法使用 SemanticModel.GetTypeInfo 获取对象的TypeInfo。您必须创建一个新的语义模型,如下所示:
foreach (var tree in context.SemanticModel.Compilation.SyntaxTrees)
{
var compilation = CSharpCompilation.Create("MyCompilation",
syntaxTrees: new[] { tree }, references: new List<MetadataReference>());
var syntaxRoot = tree.GetRoot();
var model = compilation.GetSemanticModel(tree);
var targetMethod = syntaxRoot.DescendantNodes().OfType<MethodDeclarationSyntax>().FirstOrDefault(f => f.Identifier.ToString() == "Class name to find");
if (targetMethod == null)
continue;
var typeInfo = model.GetTypeInfo(targetMethod.First().ParameterList.Parameters[i].ChildNodes().First());
// Do any thing with typeInfo
}