Roslyn:如何将多个项目的编译合并为一个单一的编译

本文关键字:编译 单一 一个 合并 项目 Roslyn | 更新日期: 2023-09-27 17:57:30

是否可以将每个项目的所有编译合并为一个编译?我目前正在研究静态代码分析器,因此,例如,当一种方法调用来自同一解决方案中另一个项目的另一个方法时,当我尝试使用 compilation.GetSemanticModel(SyntaxTree) 获取语义模型时,会出现错误,因为将另一个项目的类的SyntaxTree传递到当前项目的Compilation会破坏我的代码。

编辑:我想获取每个项目的引用和语法树并将它们组合在一起,然后基于它创建一个编译。

        List<MetadataReference> refs = new List<MetadataReference>();
        List<SyntaxTree> syntaxtrees = new List<SyntaxTree>();
        foreach (var project in projectToAnalyze)
        {
            Compilation compilation = project.GetCompilationAsync().Result;
            var references = compilation.References;
            refs.AddRange(references);
            var trees = compilation.SyntaxTrees;
            syntaxtrees.AddRange(trees);
            //analysis(project, config, compilation);
        }

        var mycompilation = CSharpCompilation.Create("test").AddReferences(refs).AddSyntaxTrees(syntaxtrees);

但是,尽管我这样做没有出错,但某些操作现在似乎不起作用。例如,当我现在使用SymbolFinder.FindImplementationsAsync时,它不再返回我的实现。

编辑2:例如MyAnalyzer:

class MyAnalyzer {
    private Compilation compilation;
    private SemanticModel model;
    private SyntaxTree tree;
    public MyAnalyzer(SyntaxTree tree, Compilation compilation) {
        this.compilation = compilation;
        this.tree = tree;
        this.model = compilation.GetSemanticModel(tree);
    //Various override Visit functions for analysis
    public override void VisitInvocationExpression(node) {
         //
         //lets say i just pass the syntaxtree belonging to ClassB
         //into a new instance of MyAnalyzer
         MyAnalyzer newAnalysis = new MyAnalyzer(classB's syntaxtree, this.compilation)
    }
}

要分析的代码:

class A {
ClassB B = new ClassB();
B.method();
}

我通过从我的Main.cs传入树和编译来运行我的分析器,如果假设ClassB来自同一解决方案中的另一个项目,那么如果我尝试在VisitInvocationExpression中创建一个新的分析实例时会出现错误,因为我通过了当前实例编译compilation.GetSemanticModel(tree)在这里不起作用, this.compilation,进入新的实例,并且由于ClassBSyntaxTree来自另一个项目。因此,我提出了将编译合并为一个编译的想法。

Roslyn:如何将多个项目的编译合并为一个单一的编译

我必须解决的问题的解决方案是,我没有将编译合并为 1 个单个编译,而是围绕语句做了一个 try-catch 块 compilation.GetSemanticModel(tree) ,如果我传递给类的编译不包含tree,则catch块将循环遍历IEnumerable<Project>的全局变量,从而存储我正在分析的Solution的项目,并循环访问每个项目的编译以查找包含树的编译。