Get a Tree Node Under Caret
What you should know beforehand:
Examples (?):
Getting a tree node under the current caret position is a very typical task when implementing a navigation or any other tree-node-dependent feature. Actually, there are many ways of obtaining the tree node depending on the context. For example, when implementing context navigation, you can use the GetSelectedTreeNode method of the IDataContext object. E.g.:
Nevertheless, if you need a more generic (context-independent) get-node-under-caret function implementation, see the example below:
Notes
The solution component
NodeUnderCaretDetectorhas the publicIProperty-NodeUnderCaret. You can use this property to obtain the tree node under the caret at any moment of time.The
NodeUnderCaret.Valueis updated each time the caret is moved. This is implemented by means of the legacyCaretMovedevent handler.The
GetTreeNodeUnderCaret()method performs all the work - it returns theITreeNodeelement under the caret.The
textControlinstance (ITextControl) allows working with the currently opened text file as if you worked with a text editor. Here we obtain the current caret offset by callingtextControl.Caret.Offset().Note that, formally speaking,
textControlknows nothing about the code inside itself - it simply renders the content it gets from anIDocumentinstance.By knowing the document, we can obtain the IProjectFile (
_documentManager.TryGetProjectFile) instance - it provides the API to work with the file's syntax tree.From the
IProjectFile, we obtain, one after another IPsiSourceFile and IFile (the main element of the PSI syntax tree).IFileprovides theFindNodeAt()method that returns the node by the specified range.Note that to prevent conflicts with user input, we must obtain the read lock before calculating the node under the caret. This is done by means of the special method of the
IShellLocksinterface:_shellLocks.QueueReadLock(...).