How to add a PsiElement as a child of another PsiElement?
I tried to add some variable declaration inside a file and I used the following code.
```
StringBuilder tag = new StringBuilder("private static final String TAG = \"LoginActivity\";"); StringBuilder RcAuth = new StringBuilder("private static final int RC_AUTH = 100;"); PsiStatement psiTag = elementFactory.createStatementFromText(tag.toString(),psiClass); PsiStatement psiRcAuth = elementFactory.createStatementFromText(RcAuth.toString(),psiClass); PsiElement tage = psiClass.addBefore(psiTag,createAuth); PsiElement rcauth = psiClass.addAfter(psiRcAuth,tage);
```
the problem is that all the declarations are added within one line i.e, int a=b;String s;
what should I do in order to add the second variable after the first one like the following:
int a=b;
String s;
Thanks
Please sign in to leave a comment.
I strongly advise against adding whitespaces manually. It may contradict user's code style settings.
I'd say that you create `PsiField` with `createStatementFromText` method, you should rather use `com.intellij.psi.impl.PsiElementFactoryImpl#createFieldFromText` instead. I guess, when you would do that, formatter will automatically insert line breaks between field declarations. If not, you may explicitly call `com.intellij.psi.codeStyle.CodeStyleManager#reformat(com.intellij.psi.PsiElement)` on created elements.
Anna
Create a `new PsiWhiteSpaceImpl("\n");` and add it to the PSI tree just like you are adding the other PsiElements you are creating.
Thank you very much for the hints I will try to use `com.intellij.psi.impl.PsiElementFactoryImpl#createFieldFromText` first.
Thanks
@Anna , how can I get instance of 'PsiElementFactoryImpl'? because I look at the class, and it seems that we don't have 'getnstance()' method.
Sorry, I should point to the api method, it's `com.intellij.psi.PsiJavaParserFacade#createFieldFromText`, the same factory you use to create statements
It is not my experience that code formatting uniformly adds newlines between statements that are initially placed on the same line -- this is true for Java, but not all languages. However, when newlines do occur, it *does* add proper indentation.
So, if using Anna's approach works for your language, that is a proper solution. If it doesn't, you can certainly add "\n" in your text between the statements to get `createFieldFromText` to give the proper formatting.
I tried to solve the problem based on the solution provided by @Anna, but, it make my plugin didn't work properly. it make problems with the part that add the code inside the Oncreat() method of the application. I got the following errors.
'''
2018-10-19 17:37:57,960 [ 79262] ERROR - api.util.objectTree.ObjectNode - null
java.lang.NullPointerException
at com.intellij.psi.impl.source.tree.ChangeUtil.prepareAndRunChangeAction(ChangeUtil.java:152)
at com.intellij.psi.impl.source.tree.CompositeElement.addChild(CompositeElement.java:613)
at com.intellij.psi.impl.source.tree.CompositeElement.addChildren(CompositeElement.java:706)
at com.intellij.psi.impl.source.codeStyle.CodeEditUtil.addChildren(CodeEditUtil.java:67)
at com.intellij.psi.impl.source.tree.CompositeElement.addInternal(CompositeElement.java:481)
at com.intellij.psi.impl.source.tree.java.PsiCodeBlockImpl.addInternal(PsiCodeBlockImpl.java:171)
at com.intellij.psi.impl.source.tree.LazyParseablePsiElement.addInnerBefore(LazyParseablePsiElement.java:348)
at com.intellij.psi.impl.source.tree.LazyParseablePsiElement.add(LazyParseablePsiElement.java:176)
at eu.fbk.STAnD.Utill.InsertCodeUtils.maybeAddStatementToMethod(InsertCodeUtils.java:76)
at eu.fbk.STAnD.Utill.InsertCodeUtils.maybeAddStatementsToMethod(InsertCodeUtils.java:61)
at eu.fbk.STAnD.InsertCodeHandler$1.run(InsertCodeHandler.java:50)
at com.intellij.openapi.application.RunResult.run(RunResult.java:35)
at com.intellij.openapi.command.WriteCommandAction.lambda$null$1(WriteCommandAction.java:265)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:1038)
at com.intellij.openapi.command.WriteCommandAction.lambda$performWriteCommandAction$2(WriteCommandAction.java:264)
at com.intellij.openapi.command.WriteCommandAction.lambda$doExecuteCommand$4(WriteCommandAction.java:322)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:139)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:107)
at com.intellij.openapi.command.WriteCommandAction.doExecuteCommand(WriteCommandAction.java:324)
at com.intellij.openapi.command.WriteCommandAction.performWriteCommandAction(WriteCommandAction.java:262)
at com.intellij.openapi.command.WriteCommandAction.execute(WriteCommandAction.java:244)
at eu.fbk.STAnD.InsertCodeHandler.invoke(InsertCodeHandler.java:62)
at eu.fbk.STAnD.GenerateAction.actionPerformed(GenerateAction.java:35)
at com.intellij.openapi.actionSystem.ex.ActionUtil$1.run(ActionUtil.java:220)
at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAware(ActionUtil.java:237)
at com.intellij.ui.popup.ActionPopupStep.performAction(ActionPopupStep.java:203)
at com.intellij.ui.popup.ActionPopupStep.performAction(ActionPopupStep.java:191)
at com.intellij.ui.popup.ActionPopupStep.lambda$onChosen$2(ActionPopupStep.java:185)
at com.intellij.openapi.application.TransactionGuardImpl.performUserActivity(TransactionGuardImpl.java:195)
at com.intellij.ui.popup.AbstractPopup.lambda$dispose$8(AbstractPopup.java:1409)
at com.intellij.util.ui.UIUtil.invokeLaterIfNeeded(UIUtil.java:3097)
at com.intellij.ide.IdeEventQueue.ifFocusEventsInTheQueue(IdeEventQueue.java:176)
at com.intellij.ide.IdeEventQueue.executeWhenAllFocusEventsLeftTheQueue(IdeEventQueue.java:132)
at com.intellij.openapi.wm.impl.FocusManagerImpl.doWhenFocusSettlesDown(FocusManagerImpl.java:190)
at com.intellij.openapi.wm.impl.IdeFocusManagerImpl.doWhenFocusSettlesDown(IdeFocusManagerImpl.java:58)
at com.intellij.ui.popup.AbstractPopup.dispose(AbstractPopup.java:1403)
at com.intellij.ui.popup.WizardPopup.dispose(WizardPopup.java:160)
at com.intellij.ui.popup.list.ListPopupImpl.dispose(ListPopupImpl.java:307)
at com.intellij.ui.popup.PopupFactoryImpl$ActionGroupPopup.dispose(PopupFactoryImpl.java:289)
at com.intellij.openapi.util.Disposer$1.execute(Disposer.java:48)
at com.intellij.openapi.util.Disposer$1.execute(Disposer.java:44)
at com.intellij.openapi.util.objectTree.ObjectNode$1.execute(ObjectNode.java:138)
at com.intellij.openapi.util.objectTree.ObjectNode$1.execute(ObjectNode.java:107)
at com.intellij.openapi.util.objectTree.ObjectTree.executeActionWithRecursiveGuard(ObjectTree.java:182)
at com.intellij.openapi.util.objectTree.ObjectNode.execute(ObjectNode.java:107)
at com.intellij.openapi.util.objectTree.ObjectTree.executeAll(ObjectTree.java:151)
at com.intellij.openapi.util.Disposer.dispose(Disposer.java:129)
at com.intellij.openapi.util.Disposer.dispose(Disposer.java:125)
at com.intellij.ui.popup.WizardPopup.disposeAllParents(WizardPopup.java:263)
at com.intellij.ui.popup.list.ListPopupImpl.handleNextStep(ListPopupImpl.java:442)
at com.intellij.ui.popup.list.ListPopupImpl._handleSelect(ListPopupImpl.java:396)
at com.intellij.ui.popup.list.ListPopupImpl.handleSelect(ListPopupImpl.java:342)
at com.intellij.ui.popup.PopupFactoryImpl$ActionGroupPopup.handleSelect(PopupFactoryImpl.java:309)
at com.intellij.ui.popup.list.ListPopupImpl$MyMouseListener.mouseReleased(ListPopupImpl.java:501)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:290)
at java.awt.Component.processMouseEvent(Component.java:6533)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at com.intellij.ui.popup.list.ListPopupImpl$MyList.processMouseEvent(ListPopupImpl.java:552)
at java.awt.Component.processEvent(Component.java:6298)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:90)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:781)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:718)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:382)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
2018-10-19 17:37:58,050 [ 79352] ERROR - api.util.objectTree.ObjectNode - IntelliJ IDEA 2018.2.1 Build #IC-182.3911.36
2018-10-19 17:37:58,053 [ 79355] ERROR - api.util.objectTree.ObjectNode - JDK: 1.8.0_151
2018-10-19 17:37:58,055 [ 79357] ERROR - api.util.objectTree.ObjectNode - VM: Java HotSpot(TM) 64-Bit Server VM
2018-10-19 17:37:58,056 [ 79358] ERROR - api.util.objectTree.ObjectNode - Vendor: Oracle Corporation
2018-10-19 17:37:58,057 [ 79359] ERROR - api.util.objectTree.ObjectNode - OS: Mac OS X
2018-10-19 17:37:58,058 [ 79360] ERROR - api.util.objectTree.ObjectNode - Last Action: GenerateCodeTest
'''
So you add a field inside `maybeAddStatementToMethod`? Or you have now completely different methods?
No, I didn't add a field to `maybeAddStatementToMethod`. I have two different methods, one in order to add code inside the Oncreate() method, and the other one for adding code outside the aforementioned method like the following.
public class GenerateAction extends AnAction {private InsertCodeHandler insertCodeHandler;
private Project myProject;
@Override
public void actionPerformed(AnActionEvent e) {
PsiClass psiclass = getPsiClassFromContext(e);
insertCodeHandler = new InsertCodeHandler(psiclass);
myProject = psiclass.getProject();
e.getPresentation().setEnabled(psiclass != null);
GenerateDialog dlg = new GenerateDialog (psiclass);
dlg.show();
if (dlg.isOK()) {
generateComparable(psiclass); // this is the code that add the code outside the function that i used your
method to reformat it
insertCodeHandler.invoke(myProject);// this part call `maybeAddStatementToMethod` and inside the method it tries to add the code based on createStatementFromText()
}
}
Please note that I advised not to call reformat but to call correct `create` methods and add members to the correct place in the class, then formatter would add all necessary whitespaces automatically.
But anyway, your code fails on adding an element, so it looks like that you try to add element to the invalid parent, cause you remember `psiClass` in the `insertCodeHandler` which may be invalidated during your previous actions.