2016-12-02 2 views
0

Я пытаюсь использовать SDK Roslyn и StackExchange.Precompilation (спасибо!) Для реализации аспектов, ориентированное программирование на C# 6. Моя конкретная проблема прямо сейчас, начиная с экземпляра IdentifierNameSyntax, я хочу найти «тип члена» (метод, свойство, поле, var и т. Д.), К которому относится идентификатор. (Как это может быть сделано?Используя Roslyn, если у меня есть IdentifierNameSyntax, могу ли я найти тип элемента, к которому он относится (поле, свойство, метод ...)


фон:

Первая проверка концепции Я работаю на некотором старый добрый контракт дизайна по-. У меня есть NonNullAttribute, который может применяться к значениям параметров, свойств или методов. Наряду с атрибутом существует класс, реализующий интерфейс StackExchange.Precompilation.ICompileModule, который при компиляции будет вставлять нулевые проверки отмеченных параметров или возвращаемых значений.

Это та же идея, что и PostSharp's NonNullAttribute, но преобразование выполняется на одном из деревьев синтаксиса Roslyn, а не на уже скомпилированной сборке. Он также похож на Code Contracts, но с подходом с декларативным атрибутом и снова работает с синтаксическими деревьями, а не с IL.

Например, этот исходный код:

[return: NonNull] 
public string Capitalize([NonNull] string text) { 
    return text.ToUpper(); 
} 

будет преобразован в это во время прекомпиляции:.

[return: NonNull] 
public string Capitalize([NonNull] string text) { 
    if (Object.Equals(text, null)) 
     throw new ArgumentNullException(nameof(text)); 

    var result = text.ToUpper(); 
    if (Object.Equals(result, null)) 
     throw new PostconditionFailedException("Result cannot be null."); 
    return result; 
} 

(PostconditionFailedException обычая исключение, которое я сделал комплимент ArgumentException для возвращаемых значений Если уже есть что-то подобное в рамке, пожалуйста, дайте мне знать.)

Для свойств с этим атрибутом есть wou ld - аналогичное преобразование, но с предварительными условиями и постусловиями, реализованными отдельно в аксессуарах set и get соответственно.


Конкретная причина, мне нужно найти «тип элемента» идентификатора здесь для оптимизации по реализации постусловий. Обратите внимание, что в примере после компиляции значение, которое было бы возвращено, сохраняется в локальной переменной, проверяется, а затем возвращается локаль. Это хранилище необходимо для преобразования операторов return, которые оценивают метод или сложное выражение, но если возвращаемое выражение является только ссылкой на поле или локальную переменную, создание этого временного хранилища является расточительным.

Итак, когда return заявление сканируется, я сначала проверить, если оператор имеет вид ReturnKeyword - IdentifierSyntaxToken - SemicolonToken. Если это так, мне нужно проверить, к чему относится этот идентификатор, поэтому я избегаю локального распределения переменных, если референт является полем или var.

Update Для больше контекста, проверить проект это со ссылкой на на GitHub.

ответ

1

Чтобы определить символ, к которому привязан идентификатор, вам необходимо использовать SemanticModel.GetSymbolInfo.

Смежные вопросы