Discrepancies between Idea and Rider for PsiElement


Hi all! I have faced with strange issue when I try to get method of class from the beginning to the end. 

I have an action from StructureView 

public void actionPerformed(@NotNull AnActionEvent e) {
TextRange range = e.getData(CommonDataKeys.PSI_ELEMENT).getTextRange();

It work fine for Idea and Java classes (I can have offsets for whole method).

But when I tryed to test it in Rider and C++ (.cpp of .h doesn't matter), the code above returns offsets only for method name.

How can I get whole method offsets for C++ in Rider (from the begining to closed brace)?

I've used selection for offsets, so

Idea and Java  (selected even with annotation):

Rider and C++ (only word qwe is selected):

What am I doing wrong? Thx!

UPD: Here is PsiViewer output, so I can't use Psi in this case, right? How can I achieve the goal in other way?

UPD1: I've just checked Rider 2022, Psi for C++ is implemented there. Seems like it's issue for versions before. But main question is same: how can I get all text related to method for any C-like lang implementation or at least Java and C++. My current solution for C++ for Rider 2022 seems pretty ugly due to discrepancies in C++ Psi and Java Psi )

private TextRange findCppRange(PsiFile psiFile, int textOffset) {
@Nullable PsiElement base = psiFile.findElementAt(textOffset).getParent();
TextRange range = base.getTextRange();

while (base.getNextSibling() != null) {
PsiElement sibling = base.getNextSibling();
if (sibling instanceof CppBlock) {
range = TextRange.create(range.getStartOffset(), sibling.getTextRange().getEndOffset());
if (sibling instanceof CppCompositeElement) {
range = TextRange.create(range.getStartOffset(), sibling.getTextRange().getEndOffset());
base = sibling;

return range;
1 comment
Official comment

Hi! Rider has a more complicated architecture than other IntelliJ based IDEs. Its language processing and language features are handled by a separate process, which is actually ReSharper (JetBrains' plugin for Visual Studio). This allows Rider to use the IDE platform we've built in the form of the IntelliJ Platform, while also reusing all of the features and development spent over many years building ReSharper. You can read more about Rider's architecture in this Code magazine article.

As such, Rider doesn't really have a PSI in the IntelliJ "frontend". Instead, its main PSI is in the ReSharper based out of process "backend", which is where all of the language analysis and updating lives. This is the same for C# and .NET and also for Rider C++. There is a simplified PSI on the frontend, with only as much of the language supported as is required for certain features. For example, the C# PSI doesn't provide nodes for the contents of method bodies. These features are usually lexical in nature - so there is no semantic resolution on the frontend, and no references, etc.

Hopefully, the PSI that is available to you is enough to fulfil the needs of your plugin. If not, then you'll need to take an optional dependency on Rider, and create a .NET based plugin that can access the full PSI and get the required information. This can be passed back to the frontend via the same protocol that Rider uses to talk between the frontend and backend - it is an extensible protocol.

Please sign in to leave a comment.