Комментарии 13
Хорошая работа!
Интересно, все-таки, будет ли это работать на 5-ом решарпере?
Интересно, все-таки, будет ли это работать на 5-ом решарпере?
0
Несколько замечаний по примеру:
1) В R# уже есть базовый класс дня написания Context Actions. Это класс BulbItemImpl. Его можно использовать примерно так:
Плюсы BulbItemImpl в том, что он будет корректно работать в случае изменений в нескольких файлах (например, вы меняете что-то в иерархии). Для долгих операций этот класс будет показывать окошко с прогресом. А так, конечно, разницы большой нет.
2) using (ReadLockCookie.Create()) {… } — делать в CA не надо
3) Использовать LowLevelModificationUtil нельзя. На то они и LowLevel. В этом просто примере это работет (хотя в R# 5 вообще-то должно упасть с исключением), но в более сложных случаях разрушит цивилизацию. Вместо этого надо использовать метод ICSharpExpression.ReplaceBy. И вообще, обычно все узлы синтаксического дерева снабнажены методами для изменения самих себя.
4) Лучше стараться не переходить к TreeNode (т.е. вызывать метод ToTreeNode), которые содержат в себе уже не только семантическую информацию, а еще и синтаксическую. Например, в давнном CA все вызовы ToTreeNode избыточны. Но это замечаение больше по стилю: интерфейс TreeNode менее стабилен и менее понятен (много синтаксического «мусора»).
1) В R# уже есть базовый класс дня написания Context Actions. Это класс BulbItemImpl. Его можно использовать примерно так:
class MyCA : BulbItemImpl, IContextAction { private readonly ICSharpContextActionDataProvider myProvider; protected MyCa(ICSharpContextActionDataProvider provider) { myProvider = provider; } public bool IsAvailable(IUserDataHolder cache) { return ...; } public override string Text { get { return "My menu item text"; } } protected override Action<ITextControl> ExecuteTransaction(ISolution solution, IProgressIndicator progress) { //Do Something //here you can return 'null' return control => { //Do something with caret, selection, etc. //Ex: control.Caret.MoveTo(myElement.GetDocumentRange().TextRange.StartOffset); }; } }
Плюсы BulbItemImpl в том, что он будет корректно работать в случае изменений в нескольких файлах (например, вы меняете что-то в иерархии). Для долгих операций этот класс будет показывать окошко с прогресом. А так, конечно, разницы большой нет.
2) using (ReadLockCookie.Create()) {… } — делать в CA не надо
3) Использовать LowLevelModificationUtil нельзя. На то они и LowLevel. В этом просто примере это работет (хотя в R# 5 вообще-то должно упасть с исключением), но в более сложных случаях разрушит цивилизацию. Вместо этого надо использовать метод ICSharpExpression.ReplaceBy. И вообще, обычно все узлы синтаксического дерева снабнажены методами для изменения самих себя.
4) Лучше стараться не переходить к TreeNode (т.е. вызывать метод ToTreeNode), которые содержат в себе уже не только семантическую информацию, а еще и синтаксическую. Например, в давнном CA все вызовы ToTreeNode избыточны. Но это замечаение больше по стилю: интерфейс TreeNode менее стабилен и менее понятен (много синтаксического «мусора»).
+3
Спасибо, учту. Не подскажите где взяли инфу? Я сколько в интернете не искал так ничего дельного и не нашел.
0
Взял я эту информацию из личного опыта разработки R#. На самом деле, если вы действительно заинтересованы в разработке плагинов (для себя или на благо общества), то не стесняйтесь спрашивать тут: www.jetbrains.net/devnet/community/resharper
Там, правда, принято общаться по-английски. В любом случае можете написать прямо мне. Мы с удовольствием отвечаем на вопросы наших пользователей.
Еще по поводу вашего примера хочу добавить две вещи: ToTreeNode никогда не возвращает null. Методы CSharpElementFactory никогда не возвращают null, а в случае ошибки бросают исключение. Зная эти вещи, вы можете сильно улучшить читаемость кода, убрав лишние проверки.
Удачи в разработке! )
Там, правда, принято общаться по-английски. В любом случае можете написать прямо мне. Мы с удовольствием отвечаем на вопросы наших пользователей.
Еще по поводу вашего примера хочу добавить две вещи: ToTreeNode никогда не возвращает null. Методы CSharpElementFactory никогда не возвращают null, а в случае ошибки бросают исключение. Зная эти вещи, вы можете сильно улучшить читаемость кода, убрав лишние проверки.
Удачи в разработке! )
0
советую набросать простенькую DSL на том же F#, например, потому что поиск по дереву в C# выглядит неопрятно, со всеми этими приведениями типов, проверками на null и так далее.
А почему бы Linq не использовать? В C# вместе с расширяющими методами получается очень серьёзный и гибкий довесок.
0
В R# 5.0 есть встроенный просмотрщик дерева, которое строит решарпер. Он устанавливается обычным инсталлятором и интегрирован в дебаггер студии. Соответственно, подсунув ему любой элемент из дерева, можно посмотреть как там все на самом деле устроено.
0
Вот это действительно круто. Я уже достаточно понаписал подобных велосипедов для Решарпера, DTE и прочих структур.
0
Кстати, может посоветуете, чтобы почитать про R#, чтобы проникнуться. Т.к. возможностей рефакторинга VS, мне вполне хватает, а проверка на ошибки на лету, не очень нужна. Зато про другие аспекты было бы интересно узнать. По возможности на русском.
0
на русском — ничего.
На английском есть вступительный документ с картинками: www.jetbrains.com/resharper/documentation/reviewers_guide.html
Есть keyboard map — емко, информативно, по делу, рекомендую всем иметь под рукой: www.jetbrains.com/resharper/documentation/documentation.html
И есть прекрасный цикл статей «31 Days of Resharper»: blog.excastle.com/2007/01/31/blog-event-the-31-days-of-resharper/
На английском есть вступительный документ с картинками: www.jetbrains.com/resharper/documentation/reviewers_guide.html
Есть keyboard map — емко, информативно, по делу, рекомендую всем иметь под рукой: www.jetbrains.com/resharper/documentation/documentation.html
И есть прекрасный цикл статей «31 Days of Resharper»: blog.excastle.com/2007/01/31/blog-event-the-31-days-of-resharper/
+2
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Расширяем ReSharper — Context Actions