How to properly create index and avoid IndexNotReadyException

Answered

Hi community!

I am contributing to the Intellij plugin for the AEM platform (https://github.com/aemtools/aemtools).

I want to implement some completion functionality that should be based on configuration model described in Java.

The configuration model is a set of property keys and can be described in 2 variants (depends on AEM version):

- in class that is annotated with special annotation (@Component/@Service) the configuration model is a list of all fields (that are also annotated with special annotation @Property) values.

- in annotation class that is annotated with @ObjectClassDefinition the configuration model is a list of methods annotated with @AttributeDefinition annotation.

I tried to implement FileBasedIndex for JavaFileType.INSTANCE, but in Indexer implementation I faced the same issue like described in https://intellij-support.jetbrains.com/hc/en-us/community/posts/360008279279-Why-I-get-IndexNotReadyException-.

This is because I take annotations of PsiClass, get their qualifiedName and compare it with acceptable list of annotations. Please, see some pseudo-code below:

val javaPsiFile = inputData.psiFile as? PsiJavaFile ?: return mutableMapOf()

val mainFileClass = javaPsiFile.classes.toList()
val innerClasses = mainFileClass.flatMap { it.findChildrenByType(PsiClass::class.java) }
val allClasses = mainFileClass + innerClasses

val osgiConfigurationDeclarations: List<ConfigurationDeclarationModel> =
allClasses.filter {
it.modifierList?.annotations?.toList().any { it.qualifiedName in listOf(ANNOTATION1, ANNOTATION2) }
}.map { ... }

 

I didn't find how can I avoid exception and, at the same time, implement indexer logic. I read about StubIndex and Gists, but didn't understand how to use them for my logic. I wanted to implement index because of possible performance issues if I run search for configuration model on each completion action.

I would be grateful if you suggest how can I solve my problem. 

Thank you in advance,

Kostiantyn Diachenko.

0
2 comments

Your index implementation depends on resolving the annotations themselves, which violates basic contract:

The data returned by DataIndexer.map() must depend only on input data passed to the method, and must not depend on any external files. Otherwise, your index will not be correctly updated when the external data changes, and you will have stale data in your index.

I’d suggest to try using builtin com.intellij.psi.search.searches.AnnotatedElementsSearch instead first to see if the performance is sufficient. Custom indexes should only ever be considered if performance problems cannot be solved using builtin indexes/stubs.

 

See also https://plugins.jetbrains.com/docs/intellij/psi-performance.html#cache-results-of-heavy-computations on how to cache resolve results (or expensive results in general).

1

Thank you for response. Will check it later and will describe solution if it is successful. 

0

Please sign in to leave a comment.