Add PsiElement to another
已回答
Hi,
I have a PHP array like this:
<?php
namespace Intranet;
return [
'factories' => [
// Api
Model\Infrastructure\Api\Adapter::class => Model\Infrastructure\Api\AdapterFactory::class,
// Command
Model\Application\Command\Application\CreateApplication::class => Model\Application\Command\Application\CreateApplicationFactory::class,
],
'foo' => [
'bar' => 'baz'
],
Model\Application\Query\Search\FindApplicationForUser::class => 'test'
];
My goal is to add a key/value inside the factories index (I want to add a ClassConstantReference \namespace\something::class not a StringLiteralExpression like 'foo').
Currently I have this code:
fun findFactoriesValuesArray(file: PsiFile): PsiElement? {
val phpReturn = PsiTreeUtil.findChildOfType(file, PhpReturn::class.java)
if (phpReturn != null) {
val arrayCreation: PhpPsiElement? = phpReturn.firstPsiChild
if (arrayCreation is ArrayCreationExpression) {
for (hashElement in arrayCreation.hashElements) {
val arrayKey = hashElement.key
if (arrayKey is StringLiteralExpression && arrayKey.text == "'factories'") {
val arrayValue = hashElement.value
val lastArrayHashElement: PsiElement = arrayValue!!.children[arrayValue.children.size - 1]
if (lastArrayHashElement is ArrayHashElement) {
println(lastArrayHashElement)
return lastArrayHashElement
}
}
}
}
}
return null
}
val projectPath = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, event.project!!.basePath.toString())
val file: VirtualFile? = VirtualFileManager.getInstance().findFileByUrl("$projectPath/module/Intranet/config/services.config.php")
val document: Document? = FileDocumentManager.getInstance().getDocument(file!!);
val psiFile: PsiFile = PhpPsiElementFactory.createPsiFileFromText(event.project!!, document!!.text)
val arrayCreation = findFactoriesValuesArray(psiFile)
if (arrayCreation != null) {
val createString: PsiElement = PhpPsiElementFactory.createPhpPsiFromText(event.project!!, ArrayHashElement::class.java, "test::class => testtest::class")
arrayCreation.add(createString)
println(psiFile.text)
}
I have an error:
java.lang.AssertionError: cannot create element from text:
<?php
test::class => testtest::class
at com.jetbrains.php.lang.psi.PhpPsiElementFactory.createPhpPsiFromText(PhpPsiElementFactory.java:294)
Why is try to add the open PHP tag and not only the string passed to the method?
Thanks.
请先登录再写评论。
I've updated my method findFactoriesValuesArray which now return the last ArrayHashElement:
private fun findFactoriesValuesArray(file: PsiFile): PsiElement? {
val phpReturn = PsiTreeUtil.findChildOfType(file, PhpReturn::class.java)
if (phpReturn != null) {
val arrayCreation: PhpPsiElement? = phpReturn.firstPsiChild
if (arrayCreation is ArrayCreationExpression) {
for (hashElement in PsiTreeUtil.getChildrenOfTypeAsList(arrayCreation, ArrayHashElement::class.java)) {
val arrayKey = hashElement.key
if (arrayKey is StringLiteralExpression && arrayKey.text == "'factories'") {
val arrayValue = hashElement.value
val lastArrayHashElement: PsiElement = arrayValue!!.children[arrayValue.children.size - 1]
if (lastArrayHashElement is ArrayHashElement) {
return lastArrayHashElement
}
}
}
}
}
return null
}
The output is:
So my string is added to the end of line of the last ArrayHashElement but I need to add a comma and a new line.
PS : I don't know why the ouput contain two PHP open tag.
Please do not create multiple threads for the same problem. https://intellij-support.jetbrains.com/hc/en-us/community/posts/360004324519-Add-some-code-to-a-file?page=1#community_comment_360000662460
Please try creating "," as separate element and append it before appending new array element
Thank you for your reply.
I add the comma like this: (It's work, after that I will need to check if the comma exists and add it if not the case)
The same exception is thrown:
java.lang.AssertionError: cannot create element from text:
<?php
'test' => 'test'
at com.jetbrains.php.lang.psi.PhpPsiElementFactory.createPhpPsiFromText(PhpPsiElementFactory.java:272)
The PsiTreeView plugin tell me an ArrayHashElement has a key => value as text
I really don't know why an exception is thrown.
I really need help. 4 evening and still not the Psi I want.
java.lang.IllegalArgumentException: Argument for @NotNull parameter 'element' of com/intellij/extapi/psi/ASTDelegatePsiElement.addAfter must not be null
at com.intellij.extapi.psi.ASTDelegatePsiElement.$$$reportNull$$$0(ASTDelegatePsiElement.java)
at com.intellij.extapi.psi.ASTDelegatePsiElement.addAfter(ASTDelegatePsiElement.java)
Why the element parameter is null?
What is the correct way to create a HashArrayElement from text?
I don't understand at all how to add a HashArrayElement to my psi element.
I found something but I don't think it's the best way to do.
if (hashArrayElement != null) {
WriteCommandAction.runWriteCommandAction(event.project!!) {
val createKey: PsiElement? = PhpPsiElementFactory.createFromText(event.project!!, ClassConstantReference::class.java, "Model\\Application\\Command\\test::class")
val createArrow: PsiElement? = PhpPsiElementFactory.createFromText(event.project!!, LeafPsiElement::class.java, "=>")
val createValue: PsiElement? = PhpPsiElementFactory.createFromText(event.project!!, ClassConstantReference::class.java, "Model\\Application\\Command\\toto::class")
val comma = hashArrayElement.parent.addAfter(PhpPsiElementFactory.createComma(event.project!!), hashArrayElement)
val arrayKey = hashArrayElement.parent.addAfter(createKey!!, comma)
val arrow = hashArrayElement.parent.addAfter(createArrow!!, arrayKey)
hashArrayElement.parent.addAfter(createValue!!, arrow)
CodeStyleManager.getInstance(event.project!!).reformat(psiFile1)
}
}
It's working, but why the reformat method don't add a new line after the comma?
It's possible to refactor this code?