Информация о типе, неправильно разрешенная семантической моделью Roslyn - PullRequest
0 голосов
/ 01 ноября 2019

Я не могу получить информацию о типе для поля, используя семантическую модель Roslyn. Он работает для полей простых типов, таких как int или string, но не для Dictionary <,>.

Вот код:

using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace SemanticsCS
{
    class Program
    {
        static void Main(string[] args)
        {
            var tree = CSharpSyntaxTree.ParseText(@"
            public class MyClass {
             int z;
             Dictionary<string, string> dict;
             int Method1() { int x = 3; return 0; }
             void Method2()
             {
                int x = Method1();
             }
        }
    }");
            // 
            Dictionary<string, string> dict;
            var Mscorlib = PortableExecutableReference.CreateFromFile(typeof(object).Assembly.Location);
            var compilation = CSharpCompilation.Create("MyCompilation",
                syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
            var model = compilation.GetSemanticModel(tree);

            //Looking at the first method symbol
            foreach (var nodeSyntax in tree.GetRoot().DescendantNodes())
                {
                var methodSymbol = model.GetSymbolInfo(nodeSyntax);
                var symbolInfo = model.GetSymbolInfo(nodeSyntax);
                var typeInfo = model.GetTypeInfo(nodeSyntax);

                if (typeInfo.Type != null)
                    Console.WriteLine(nodeSyntax.GetText() + ":" + typeInfo.Type.Kind);
            }
        }
    }
}

, когда я его запускаю, я получаю

             int :NamedType
             Dictionary<string, string> :ErrorType
string:NamedType
string:NamedType
                         int :NamedType
int :NamedType
3:NamedType
0:NamedType
                         void :NamedType
                                int :NamedType
Method1():NamedType

Я полагаю, что ErrorType является значением по умолчанию, используемым Roslyn, когда фактический типне получено.

Определение словаря должно быть из mscorlib. Может ли быть так, что он не найден? Или мне нужно что-то изменить в коде? Очевидно, он работает на одном из компьютеров моих коллег, но не на моем. Это вопрос настройки использования .Net?

1 Ответ

1 голос
/ 03 ноября 2019

Определение ссылочной сборки не достаточно, чтобы сообщить компилятору, откуда взято имя класса. Вы должны указать либо полное имя типа (System.Collections.Generic.Dictionary<string, string>), либо определить с помощью оператора using.

Чтобы помочь вам понять ошибки, вы можете взглянуть на диагностический отчет. (Из CSharpCompilation или SyntaxTree).

foreach (var d in compilation.GetDiagnostics())
{
    Console.WriteLine(CSharpDiagnosticFormatter.Instance.Format(d));
}

Это даст вам следующее:

(11,1): error CS1022: Type or namespace definition, or end-of-file expected
(4,10): error CS0246: The type or namespace name 'Dictionary<,>' could not be found (are you missing a using directive or an assembly reference?)
error CS5001: Program does not contain a static 'Main' method suitable for an entry point
(5,30): warning CS0219: The variable 'x' is assigned but its value is never used
(4,37): warning CS0169: The field 'MyClass.dict' is never used
(3,14): warning CS0169: The field 'MyClass.z' is never used

Следующая ошибка - ошибка пространства имен.

(4, 10): ошибка CS0246: не удалось найти тип или имя пространства имен Dictionary <,>> (отсутствует директива using или ссылка на сборку?)

Но вы можете видеть, что некоторыедругие там. Следующее здесь из-за дополнительных } в конце скрипта.

(11,1): ошибка CS1022: определение типа или пространства имен или ожидаемый конец файла

Конец последнего:

ошибка CS5001: Программа не содержит статический метод 'Main', подходящий для точки входа

Это потому, чтопо умолчанию компилятор пытается построить исполняемый файл вместо библиотеки. Вы можете изменить это с помощью OutputKind enum.

var compilation = CSharpCompilation.Create(
    "MyCompilation",
    syntaxTrees: new[] { tree },
    references: new[] { Mscorlib },
    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

Edit:

Если вы хотите найти OutputKind из существующего файла csproj, вы можете сделать это следующим образом: (вдохновлено это суть

// Nuget :
// https://www.nuget.org/packages/Microsoft.Build.Locator
// https://www.nuget.org/packages/Microsoft.CodeAnalysis.Workspaces.MSBuild/
// https://www.nuget.org/packages/Microsoft.CodeAnalysis

if (!MSBuildLocator.IsRegistered)
{
    MSBuildLocator.RegisterDefaults();
}
using(var wp = MSBuildWorkspace.Create()){
    var project = await wp.OpenProjectAsync(@"pathtocsprojfile.csproj");
    Console.WriteLine(project.CompilationOptions.OutputKind);
}
...