Я пытаюсь использовать 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.