How to get cursor position in the current editor?

I need the current editor position in the PsiReference.resolve(), PsiReferenceProvider.getReferencesByElement() methods.

I try calculate the position in the code below:
Editor editor = (Editor) DataManager.getInstance().getDataContext().getData(DataConstants.EDITOR);
int offset = editor.getCaretModel().getOffset();

Is there another way (better performance, simpler)?

2
9 comments
Avatar
Permanently deleted user

Yes, this is the right way to do it.

1

The answer seems to be outdated, despite still referenced from http://www.jetbrains.org/intellij/sdk/docs/faq.html.

Both `com.intellij.ide.DataManager#getDataContext()` and `com.intellij.openapi.actionSystem.DataConstants` are deprecated. 

Also see very promising `com.intellij.openapi.actionSystem.CommonDataKeys#CARET` but still not get how those DataKeys works...

Would highly appreciate any response from JetBrainers...

0

com.intellij.ide.DataManager#getDataContext() javadoc:

* @deprecated use either {@link #getDataContext(Component)} or {@link #getDataContextFromFocus()}

com.intellij.openapi.actionSystem.DataConstants javadoc:

* @deprecated use {@link DataKeys} and {@link DataKey#getData} instead
0

Unfortunately, RTFM is a valid answer for any question as well as not helpful at all...

In my case, I need to determine the caret position from

com.intellij.lang.documentation.DocumentationProvider#generateDoc

So I have nothing except selected PsiElement in the Editor. It also looks like the method above not called from EDT (the event dispatch thread), which causes additional problems...

After observing IntelliJ source code as well as https://www.jetbrains.org/intellij/sdk/docs/basics/architectural_overview/general_threading_rules.html and https://www.jetbrains.org/intellij/sdk/docs/tutorials/editor_basics/working_with_text.html#getting-an-instance-of-the-active-editor-from-an-action-event 

the only working solution I found is the next:

private int getCaretOffsetInElement(PsiElement element){
Editor[] editor = new Editor[1];
ApplicationManager.getApplication()
.invokeLater( () -> editor[0] = FileEditorManager.getInstance(element.getProject()).getSelectedTextEditor());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return editor[0].getCaretModel().getOffset() - element.getTextRange().getStartOffset();
}

I can feel code smell from the other room... :(

Definitely should be a better way to obtain current Editor having only selected PsiElement...

Any constructive advice will be highly appreciated.

 

0

Sorry, my previous answer was only about the fact of deprecation and possible replacements for these elements.

It is not 100% safe to assume the PsiElement always has an open Editor available in #generateDoc().

What do you need caret position for exactly when generating docs? Maybe there's a different way to achieve it.

 

0

Thank you for pointing out the deprecations replacement. I did "meditate" a couple of hours on IDEA sources and I still didn't get how to use those alternatives. Would highly appreciate if anyone provides a working code (like one at the topic starter comment before deprecations took place).

In my case I know for sure PsiElement has open Editor for it, so the hack above is working... but it's sooo ugly.

And I just need to find if QuickDoc been called on variable reference or not (JetBrains CMake parser bundled into CLion used):

set(CMAKE_ASM_NASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/yasm${ANDROID_TOOLCHAIN_SUFFIX}")

PS The quoted part is one PsiElement.

0

Recent update:
Simplest but error prone way with usage of deprecated DataManager#getDataContext() is:
int offset = CommonDataKeys.CARET.getData(DataManager.getInstance().getDataContext()).getOffset();

To get offset even on unfocused editor:
final DataContext dataContext = DataManager.getInstance().getDataContext();
final Editor editor = CommonDataKeys.EDITOR_EVEN_IF_INACTIVE.getData(dataContext);
int offset = editor == null ? -1 : editor.getCaretModel().getOffset();

Looks like the proper way to get DataContext will be usage of DataManager#getDataContextFromFocusAsync() and then deal with returned Promise

0

Since 201 the 

PsiEditorUtil.findEditor(psiElement);

seems to be the easiest solution to obtain Editor (require EDT)

0

For the cases like mine: offset in the editor needed for use in

DocumentationProvider#generateDoc

the simplest workaround is overriding

DocumentationProvider#getCustomDocumentationElement

and use(remember) targetOffset param from there.

 

0

Please sign in to leave a comment.