Можно ли использовать семантическую модель Roslyn для идентификации зависимости, введенной через nameof и использование C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Можно ли использовать семантическую модель Roslyn для идентификации зависимости, введенной через nameof и использование

Сообщение Anonymous »

Рассмотрим следующий тривиальный код C#:

Код: Выделить всё

public class Type1
{
public const int I = 1;
public static void f(){}
}
и

Код: Выделить всё

using static Type1;
public class Type2
{
public static string X = nameof(f);
public static int Y = I;
}
Мой инструмент определяет все зависимости между типами. Большинство зависимостей можно выявить, исследовав двоичный код. Однако некоторые зависимости существуют строго во время компиляции, а не во время выполнения. Например, в зависимости от константных значений (например, Type1.I) или директивы nameof, встроенных компилятором. Таким образом, nameof(f) превращается в «f», а Y = I — в Y = 1.
Только синтаксический анализ выявить эти зависимости также недостаточно. В таких тривиальных случаях это выполнимо, но в целом неосуществимо (если только не реализовать компилятор с нуля).
Что оставляет анализ с использованием семантической модели. Это здорово. Он прекрасно распознает зависимости от постоянных значений. И большинство зависимостей nameof. Но это терпит неудачу, когда директива nameof ссылается на что-то, добавленное в пространство имен с помощью директивы using static.
Вот полный код, который это демонстрирует:

Код: Выделить всё

private const string CODE_1 = @"public class Type1
{
public const int I = 1;
public static void f(){}
}
";
private const string CODE_2 = @"using static Type1;
public class Type2
{
public static string X = nameof(f);
public static int Y = I;
}
";
private static readonly string[] s_netCoreReferences =
[
typeof(object).Assembly.Location,
Path.GetDirectoryName(typeof(object).Assembly.Location) + "\\System.Runtime.dll",
];

[Test]
public void NameOfOperationWithUsingStatic()
{
SyntaxTree[] syntaxTrees = [CSharpSyntaxTree.ParseText(CODE_1), CSharpSyntaxTree.ParseText(CODE_2)];
var compilation = CSharpCompilation.Create("temp", syntaxTrees,
s_netCoreReferences.Select(o => MetadataReference.CreateFromFile(o)).ToArray(),
new CSharpCompilationOptions(OutputKind.NetModule));
Assert.That(compilation.GetDiagnostics(), Is.Empty);
var model = compilation.GetSemanticModel(syntaxTrees[1]);

var syntaxNode1 = syntaxTrees[1]
.GetCompilationUnitRoot()
.DescendantNodes()
.OfType()
.FirstOrDefault(o => o.Identifier.ValueText == "nameof");
var nameofOp = (INameOfOperation)model.GetOperation(syntaxNode1.Parent);

Assert.That(nameofOp.Argument.Type, Is.Null);
Assert.That(nameofOp.Argument.ChildOperations, Is.Empty);

var syntaxNode2 = syntaxTrees[1]
.GetCompilationUnitRoot()
.DescendantNodes()
.OfType()
.Where(o => o.Declaration.Variables[0].Identifier.ValueText == "Y")
.Select(o => o.Declaration.Variables[0].Initializer.Value)
.FirstOrDefault();
var fieldOp = (IFieldReferenceOperation)model.GetOperation(syntaxNode2);

Assert.That(fieldOp.Field.ContainingType.Name, Is.EqualTo("Type1"));
Assert.That(fieldOp.Field.Name, Is.EqualTo("I"));
}
Обратите внимание на эти утверждения:

Код: Выделить всё

Assert.That(nameofOp.Argument.Type, Is.Null);
Assert.That(nameofOp.Argument.ChildOperations, Is.Empty);
Это указывает на то, что INameOfOperation, возвращаемый семантической моделью, не может идентифицировать, что nameof ссылается на функцию Type1.f.Семантическая модель работала нормально для константы Type1.I, которая фиксируется утверждениями:

Код: Выделить всё

Assert.That(fieldOp.Field.ContainingType.Name, Is.EqualTo("Type1"));
Assert.That(fieldOp.Field.Name, Is.EqualTo("I"));
Мой вопрос: что можно сделать с nameof в этом конкретном сценарии? Я хочу подчеркнуть, что семантическая модель, кажется, работает нормально во всех других случаях использования nameof.

Подробнее здесь: https://stackoverflow.com/questions/792 ... through-na
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»