PsiAugmentProvider throws ArrayStoreException Follow
Answered
I'm trying to make IDEA think that class member is present, using implementation of PsiAugmentProvider.
I created a @Singleton annotation:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Singleton {
String factoryMethod() default "get";
}
Use it like this:
@Singleton
public class SingletonExample {}
I started with providing a static method first. Field and constructor are on the way.
And my implementation of PsiAugmentProvider is:
public class AugmentProvider extends PsiAugmentProvider {
@NotNull
@Override
public <T extends PsiElement> List<T> getAugments(@NotNull PsiElement element, @NotNull final Class<T> type, @Nullable String nameHint) {
List<T> emptyResult = new ArrayList<>();
if (!(element instanceof PsiClass)) {
return emptyResult;
}
PsiClass psiClass = (PsiClass) element;
if (psiClass.isAnnotationType() || psiClass.isInterface()) {
return emptyResult;
}
final String annotationName = "my.pack.Singleton";
if (!psiClass.hasAnnotation(annotationName)) {
return emptyResult;
}
PsiAnnotation annotation = psiClass.getAnnotation(annotationName);
PsiLiteralExpression nameAttribute = (PsiLiteralExpression) annotation.findAttributeValue("factoryMethod");
String name = (String) nameAttribute.getValue();
List<T> psis = new ArrayList<>();
LightMethodBuilder method = new LightMethodBuilder(psiClass.getManager(), name)
.setModifiers("public", "static")
.setMethodReturnType(psiClass.getName())
.setBaseIcon(IconLoader.getIcon("/icons/icon.png", this.getClass()));
method.setNavigationElement(annotation);
psis.add((T) method);
return psis;
}
}
But IDEA throws an exception:
java.lang.ArrayStoreException: com.intellij.psi.impl.light.LightMethodBuilder
at com.intellij.util.ArrayUtil.mergeCollections(ArrayUtil.java:238)
at com.intellij.psi.impl.source.ClassInnerStuffCache.calcFields(ClassInnerStuffCache.java:120)
at com.intellij.psi.impl.source.ClassInnerStuffCache.lambda$getFields$0(ClassInnerStuffCache.java:47)
at com.intellij.psi.util.CachedValuesManager.lambda$getProjectPsiDependentCache$0(CachedValuesManager.java:134)
at com.intellij.psi.util.CachedValuesManager$1.compute(CachedValuesManager.java:158)
at com.intellij.psi.impl.PsiCachedValueImpl.doCompute(PsiCachedValueImpl.java:39)
at com.intellij.util.CachedValueBase.lambda$getValueWithLock$3(CachedValueBase.java:227)
at com.intellij.util.CachedValueBase.computeData(CachedValueBase.java:42)
at com.intellij.util.CachedValueBase.lambda$getValueWithLock$4(CachedValueBase.java:227)
at com.intellij.openapi.util.RecursionManager$1.computePreventingRecursion(RecursionManager.java:114)
at com.intellij.openapi.util.RecursionGuard.doPreventingRecursion(RecursionGuard.java:44)
at com.intellij.openapi.util.RecursionManager.doPreventingRecursion(RecursionManager.java:68)
at com.intellij.util.CachedValueBase.getValueWithLock(CachedValueBase.java:228)
at com.intellij.psi.impl.PsiCachedValueImpl.getValue(PsiCachedValueImpl.java:28)
at com.intellij.util.CachedValuesManagerImpl.getCachedValue(CachedValuesManagerImpl.java:72)
at com.intellij.psi.util.CachedValuesManager.getCachedValue(CachedValuesManager.java:155)
at com.intellij.psi.util.CachedValuesManager.getProjectPsiDependentCache(CachedValuesManager.java:132)
at com.intellij.psi.impl.source.ClassInnerStuffCache.getFields(ClassInnerStuffCache.java:47)
at com.intellij.psi.impl.source.PsiClassImpl.getFields(PsiClassImpl.java:276)
at com.intellij.ide.structureView.impl.java.JavaClassTreeElement.doGetOwnChildren(JavaClassTreeElement.java:73)
at com.intellij.ide.structureView.impl.java.JavaClassTreeElement.lambda$getOwnChildren$0(JavaClassTreeElement.java:68)
at com.intellij.util.SlowOperations.allowSlowOperations(SlowOperations.java:141)
at com.intellij.ide.structureView.impl.java.JavaClassTreeElement.getOwnChildren(JavaClassTreeElement.java:68)
at com.intellij.ide.structureView.impl.java.JavaClassTreeElement.getClassChildren(JavaClassTreeElement.java:40)
at com.intellij.ide.structureView.impl.java.JavaClassTreeElement.getChildrenBase(JavaClassTreeElement.java:34)
at com.intellij.ide.structureView.impl.common.PsiTreeElementBase.doGetChildren(PsiTreeElementBase.java:84)
at com.intellij.ide.structureView.impl.common.PsiTreeElementBase.lambda$getChildren$0(PsiTreeElementBase.java:74)
at com.intellij.ide.util.treeView.AbstractTreeUi.calculateYieldingToWriteAction(AbstractTreeUi.java:1715)
at com.intellij.ide.structureView.impl.common.PsiTreeElementBase.getChildren(PsiTreeElementBase.java:74)
at com.intellij.ide.structureView.impl.common.PsiTreeElementBase.getChildren(PsiTreeElementBase.java:23)
at com.intellij.ide.util.treeView.smartTree.TreeElementWrapper.initChildren(TreeElementWrapper.java:50)
at com.intellij.ide.util.treeView.smartTree.CachingChildrenTreeNode.rebuildSubtree(CachingChildrenTreeNode.java:207)
at com.intellij.ide.util.treeView.smartTree.CachingChildrenTreeNode.ensureChildrenAreInitialized(CachingChildrenTreeNode.java:41)
at com.intellij.ide.util.treeView.smartTree.CachingChildrenTreeNode.getChildren(CachingChildrenTreeNode.java:33)
at com.intellij.ide.structureView.newStructureView.StructureViewComponent$MyNodeWrapper.getChildren(StructureViewComponent.java:796)
at com.intellij.ide.util.treeView.smartTree.SmartTreeStructure.getChildElements(SmartTreeStructure.java:62)
at com.intellij.ui.tree.StructureTreeModel.getValidChildren(StructureTreeModel.java:383)
at com.intellij.ui.tree.StructureTreeModel.validateChildren(StructureTreeModel.java:299)
at com.intellij.ui.tree.StructureTreeModel.getNode(StructureTreeModel.java:293)
at com.intellij.ui.tree.StructureTreeModel.getChildren(StructureTreeModel.java:313)
at com.intellij.ui.tree.AsyncTreeModel$CmdGetChildren.getNode(AsyncTreeModel.java:545)
at com.intellij.ui.tree.AsyncTreeModel$Command.get(AsyncTreeModel.java:440)
at com.intellij.ui.tree.AsyncTreeModel$Command.get(AsyncTreeModel.java:406)
at com.intellij.util.concurrency.Invoker$Task.run(Invoker.java:314)
at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1152)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runInReadActionWithWriteActionPriority$0(ProgressIndicatorUtils.java:75)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runActionAndCancelBeforeWrite(ProgressIndicatorUtils.java:158)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runWithWriteActionPriority$1(ProgressIndicatorUtils.java:115)
at com.intellij.openapi.progress.ProgressManager.lambda$runProcess$0(ProgressManager.java:58)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:189)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$12(CoreProgressManager.java:608)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:683)
at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:639)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:607)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:60)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:176)
at com.intellij.openapi.progress.ProgressManager.runProcess(ProgressManager.java:58)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runWithWriteActionPriority(ProgressIndicatorUtils.java:112)
at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(ProgressIndicatorUtils.java:75)
at com.intellij.util.concurrency.Invoker.invokeSafely(Invoker.java:203)
at com.intellij.util.concurrency.Invoker.lambda$offerSafely$0(Invoker.java:181)
at com.intellij.util.concurrency.Invoker$Background.lambda$offer$0(Invoker.java:481)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at com.intellij.util.concurrency.SchedulingWrapper$MyScheduledFutureTask.run(SchedulingWrapper.java:223)
at com.intellij.util.concurrency.BoundedTaskExecutor.doRun(BoundedTaskExecutor.java:241)
at com.intellij.util.concurrency.BoundedTaskExecutor.access$200(BoundedTaskExecutor.java:31)
at com.intellij.util.concurrency.BoundedTaskExecutor$1.execute(BoundedTaskExecutor.java:214)
at com.intellij.util.ConcurrencyUtil.runUnderThreadName(ConcurrencyUtil.java:212)
at com.intellij.util.concurrency.BoundedTaskExecutor$1.run(BoundedTaskExecutor.java:203)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:668)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:665)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:665)
at java.base/java.lang.Thread.run(Thread.java:829)
After debugging I figured out that it may the the reason in relation between element and type parameters, but this is no more than assumption. Maybe its is not the reason.
... getAugments(@NotNull PsiElement element, @NotNull final Class<T> type, ...)
Where should I dig to solve this?
Please sign in to leave a comment.
Hi Serhii,
I think your assumption is correct. The exception is thrown from the:
and you produce a method, so there is probably a try to store a PsiMethod object in an array of PsiField.
Try to add the following condition:
Karol Lewandowski

Thank you! I got a bit further.
In dropdown menu it really appears but it cannot get resolved actually.
I changed my code to this:
And another question is:
If I need to generate fields in a class I need to create separate Augment Provider? Since It returns elements of only one type?
What is
MethodBuilder.forClass()
? I can’t find it in the platform code.I don’t think you need to create a separate
PsiAugmentProvider
. You can create conditions that will return what is needed depending on the providedtype
.Karol Lewandowski
Oh sorry, this builder is a wrapper for LightMethodBuilder:
Could you please try the following?
It worked, appreciate your help!
Karol Lewandowski
One more question regarding generated psi elements.
For a Singleton one of the required parts is private constructor.
By default Java provides public no-args constructor.
As a result my generated private constructor is ignored so I can instantiate singleton from other place.
I assume I need some functionality to delete a constructor that is implicitly defined in a class so intellij can prioritize my private constructor.
What is the best way to do this?
I figured out that I was missing a statement on LightMethodBuilder:
Now it compiles as expected.