繁体   English   中英

如何使用Roslyn SemanticModel通过ScriptCompilation获取TypeInfo

[英]How to use Roslyn SemanticModel to get TypeInfo with ScriptCompilation

我试图提取TypeInfo以获得动态脚本环境中可用成员的列表。

如果使用CSharpCompilation.Create(),则可以获取成员列表,但是当我从CSharpScript状态获得编译信息时,或使用CSharpCompilation.CreateScriptCompilation()时,都会出现异常“序列包含多个元素”。

此功能正常工作

    public List<string> Test()
    {
        var code = @"
        using System;
        var i = 5; ";

        var code2 = "i. ";

        var parseOptions = new CSharpParseOptions(kind: SourceCodeKind.Script);

        var syntaxTree = SyntaxFactory.ParseSyntaxTree(code, parseOptions);
        var syntaxTree2 = SyntaxFactory.ParseSyntaxTree(code2, parseOptions);

        var systemReference = MetadataReference.CreateFromFile(typeof(Int32).Assembly.Location);
        var compilation = CSharpCompilation.Create("foo")
                .AddReferences(systemReference)
                .AddSyntaxTrees(syntaxTree)
                .AddSyntaxTrees(syntaxTree2);

        var semanticModel = compilation.GetSemanticModel(syntaxTree2);

        var dotTextSpan = new TextSpan(code2.IndexOf("i.") + 1, 1);
        var s = syntaxTree2.GetRoot().DescendantNodes(dotTextSpan).Last();
        var memberAccessNode = (MemberAccessExpressionSyntax) s;

        var lhsType = semanticModel.GetTypeInfo(memberAccessNode.Expression).Type;

        var r = new List<string>();

        foreach (var symbol in lhsType.GetMembers())
        {
            if (!symbol.CanBeReferencedByName
                || symbol.DeclaredAccessibility != Accessibility.Public
                || symbol.IsStatic)
                continue;

            r.Add(symbol.Name);
        }

        return r;
    }

但是当使用CSharpScript代替时,出现异常

    public List<string> Test2()
    {
        var code = @"
        using System;
        var i = 5; ";

        var scriptOptions = ScriptOptions.Default;
        scriptOptions.AddReferences(typeof(Int32).Assembly);

        var scriptState = CSharpScript.RunAsync(code, scriptOptions).Result;

        var code2 = "i. ";

        var parseOptions = new CSharpParseOptions(kind: SourceCodeKind.Script);

        var syntaxTree2 = SyntaxFactory.ParseSyntaxTree(code2, parseOptions);

        var compilation = scriptState.Script.GetCompilation()
                .AddSyntaxTrees(syntaxTree2);

        var semanticModel = compilation.GetSemanticModel(syntaxTree2);

        var dotTextSpan = new TextSpan(code2.IndexOf("i.") + 1, 1);
        var s = syntaxTree2.GetRoot().DescendantNodes(dotTextSpan).Last();
        var memberAccessNode = (MemberAccessExpressionSyntax)s;

        var lhsType = semanticModel.GetTypeInfo(memberAccessNode.Expression).Type;

        var r = new List<string>();

        foreach (var symbol in lhsType.GetMembers())
        {
            if (!symbol.CanBeReferencedByName
                || symbol.DeclaredAccessibility != Accessibility.Public
                || symbol.IsStatic)
                continue;

            r.Add(symbol.Name);
        }

        return r;
    }

知道如何让它运行吗?

编辑:这是异常的完整堆栈跟踪。

"   at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)\r\n   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.IsSubmissionSyntaxTree(SyntaxTree tree)\r\n   at Microsoft.CodeAnalysis.CSharp.BinderFactory.BinderFactoryVisitor.VisitCompilationUnit(CompilationUnitSyntax compilationUnit, Boolean inUsing, Boolean inScript)\r\n   at Microsoft.CodeAnalysis.CSharp.BinderFactory.GetBinder(CSharpSyntaxNode node, Int32 position, CSharpSyntaxNode memberDeclarationOpt, Symbol memberOpt)\r\n   at Microsoft.CodeAnalysis.CSharp.BinderFactory.GetBinder(CSharpSyntaxNode node, CSharpSyntaxNode memberDeclarationOpt, Symbol memberOpt)\r\n   at Microsoft.CodeAnalysis.CSharp.SyntaxTreeSemanticModel.CreateMemberModel(CSharpSyntaxNode node)\r\n   at System.Collections.Immutable.ImmutableInterlocked.GetOrAdd[TKey,TValue](ImmutableDictionary`2& location, TKey key, Func`2 valueFactory)\r\n   at Microsoft.CodeAnalysis.CSharp.SyntaxTreeSemanticModel.GetMemberModel(CSharpSyntaxNode node)\r\n   at Microsoft.CodeAnalysis.CSharp.SyntaxTreeSemanticModel.GetTypeInfoWorker(CSharpSyntaxNode node, CancellationToken cancellationToken)\r\n   at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetTypeInfo(ExpressionSyntax expression, CancellationToken cancellationToken)\r\n   at Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetTypeInfo(SemanticModel semanticModel, ExpressionSyntax expression, CancellationToken cancellationToken)\r\n   at ScriptEngine.ScriptingHost.Test2() in D:\\Source\\ScriptEngine\\ScriptingHost.cs:line 205"

脚本编译只能有一个SyntaxTree

您应该改为将节点添加到原始SyntaxTree。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM