I have an intention which currently uses a text template using TemplateManager.createTemplate(). For various reasons I'd like to build my replacement code using the PSI rather than text, and then replace some elements in the resulting tree using a template.
Following some examples in the Community code, I have something now. I create my new PSI tree as usual, record some elements within the new tree to replace, and reformat it. I then create a template builder like this:
(document/unblock! project (document/from editor))
(let [builder (TemplateBuilderImpl. new-fn)
manager (TemplateManager/getInstance project)]
(doseq [[usage name] name-by-usage]
(.replaceElement builder ^PsiElement usage ^String name (ConstantNode. name) true))
(.startTemplate manager ^Editor editor (.buildInlineTemplate builder))))))
I'm using Clojure here, but hopefully it's somewhat clear - I call PsiDocumentManager.doPostponedOperationsAndUnblockDocument, then create a new TemplateBuilderImpl passing in a PsiElement which contains all the elements to be replaced. I call TemplateBuilderImpl#replaceElement(PsiElement, String, Expression, boolean) on each of my elements that I'd like to replace, and then call TemplateManager.startTemplate(editor, builder.buildInlineTemplate()).
What I'm finding is that the template creates the replacement strings at the wrong offsets, and I can't figure out why. Am I missing a step here in the template creation, or after manipulating the PSI?