How to Find Usages, when the Reference and the Named element are different words


I am making a plugin to support Rome Remastered modding.

There is this situation:

On file A, we have a few building definitions, lets say one of them is:

dockyard: {...}


On file B, we have the strings that should be presented on the ui, in various game situations.

{dockyard}  Dockyard
{dockyard_desc} Dockyards help you bla bla bla...
{dockyard_desc_short} Dockyards are good.


I am able to make the identifiers on file B as References that point to the Named Element identifier on file A without problem: The _desc, etch suffixes are known, and I just have my BuildingReference::resolve function return the NamedElement that matches the string that doesnt include them.

But how can I do the opposite? I read here and it seems that the Reference should be the same string as the Named Element for the Find Usages to work.

This problem (the fact that Find Usages does not work) makes the rename refactoring not work either.

Is there some way to approach this issue? Semantically, although the References and the Named Element are not the same string, they really are the same thing, and they should be able to be refactored (renamed) together, as well as appear in FInd Usages.


Any help?


Comment actions Permalink

Hi Nikolaos,
You can provide a custom com.intellij.referencesSearch Extension Point that will extend searching with the phrases you need. Example:

class CustomReferencesSearch : QueryExecutorBase<PsiReference, SearchParameters>(true) {

private val caseSensitivity = // true/false; override fun processQuery(searchParams: SearchParameters, consumer: Processor<in PsiReference>) { val elementToSearch = searchParams.elementToSearch    if (...) { // elementToSearch is your definition      searchParams.optimizer.searchWord("${elementToSearch.text}_desc", searchParams.effectiveSearchScope, caseSensitivity, elementToSearch)      searchParams.optimizer.searchWord("${elementToSearch.text}_desc_short", searchParams.effectiveSearchScope, caseSensitivity, elementToSearch)    } } }

Depending on your PsiReference.isReferenceTo() implementation, you may need some adjustments there.

Comment actions Permalink

Thank you Karol Lewandowski. It works fine now, I can find usages and rename everything at the same time.

The only problem is that apparently the context of the QueryExecutorBase is a bit special.

I get this Exception:

Read access is allowed from inside read-action (or EDT) only (see com.intellij.openapi.application.Application.runReadAction())

on various function calls initiated from the processQuery function of the QueryExecutorBase, for example on:





Comment actions Permalink

Hi Nikolaos,

QueryExecutorBase allows to pass the flag to execute code in read action. In my code snippet there is:

QueryExecutorBase<PsiReference, SearchParameters>(true)

Notice "true". Are you sure you set the same?

Comment actions Permalink

Oh thank you! I remember I was wondering what that (true) was but I dont know Kotlin, and then I forgot about it.

I appreciate :)


Please sign in to leave a comment.