Add element to PSI
Hi,
I try to add an element to a PSI but I really don't understand yet the PSI system.
A PSI is a tree with PSI element but I don't know how to add/edit/delete an element
For example I have this PHP file:
<?php
class Query {
public function handler()
{
}
}
The file is loaded like this:
URL url = ResourceUtil.getResource(getClass(), "templates", "query.php");
VirtualFile virtualFile = VfsUtil.findFileByURL(url);
PsiFile file = PsiManager.getInstance(e.getProject()).findFile(virtualFile);
After that, I don't know how to manipulate the file variable to add a PSI element and the different open source project what I'm looking seems not using the PSI like I would. Or may be I want to use it wrong.
For example if I want a new method I need a PSI for the "public" keyword, the "function" keyword, the method name, and so on?
Can you provide a simple example which add for example a method, a constructor, a field, a parameter to a method, just some simple use case and write the file in the opened project (because a PSI file loaded from VfsUtils.findFileByURL is read only)
Regards.
请先登录再写评论。
Hey.
Here are general IntelliJ guidelines on PSI concept http://www.jetbrains.org/intellij/sdk/docs/basics/architectural_overview/psi.html - it can give you more general picture.
Also consider using https://plugins.jetbrains.com/plugin/227-psiviewer plugin to discover PHP PSI structure.
About you concrete case: to copy content of read only file to the project you can do the following steps:
- Create non-physical file from it's content using com.intellij.psi.PsiFileFactory#createFileFromText
- Put this file into some directory via com.intellij.psi.PsiDirectory::add. Directory can be obtained depending on your context, you can get some by invoking PsiElement#getContainingFile#getContainingDirectory
- Obtain the class from file: com.jetbrains.php.lang.psi.PhpPsiUtil#findClass
- Create method: com.jetbrains.php.lang.psi.PhpPsiElementFactory#createMethod
- Add created method to the class. Naive solution: clazz.addBefore(method, clazz.getLastChild()), you can play with it and make it more smart.
Thanks.
I already read the psi docs, and the PsiViewer plugin is installed too.
I posting the topic because the docs does not help me.
I already try to use com.intellij.psi.PsiFileFactory#createFileFromText but I don't know how to get the content of a file from my URL object.
File file = new File(url.getFile());
with this code, the file doesn't exists :/
Where is your file located? Try to use com.intellij.openapi.vfs.VirtualFileSystem#findFileByPath (via com.intellij.openapi.vfs.LocalFileSystem#getInstance) to find it, will it help?
Yes actually I get the file like this: (see first post)
But you tell me to get a psi file with com.intellij.psi.PsiFileFactory#createFileFromText instead of PsiManager.getInstance(e.getProject()).findFile(virtualFile);
The method createFileFromText can be writable? and the findFile is read only?
com.intellij.psi.PsiFileFactory#createFileFromText will create non-physical file which is writable, but yet not present in your project, you have to add it.
PsiManager.getInstance(e.getProject()).findFile(virtualFile); can return writable or non-writable file depending on context
To obtain text of you non-writable file, please try to use com.intellij.openapi.vfs.LocalFileSystem#getInstance#findFileByPath
Thank you.
How to get the content of a file as CharSequance from a virtualFile?
I have the virtual file but how to get the content of the file as CharSequence ?
I don't know if my file path is ok for the createFileFromText parameter.
Currently, my file is stored in my plugin resources folder (resources/templates/query.php)
I finally get the CharSequence with LoadTextUtil.loadText(virtualFile)
I'm stucks with the next part :/
In your steps, you add the file to a PsiDirectory but I don't know how to get the PsiDirectory from my action.
Could you provide a simple exemple from my code because I don't understand yet the process.
Please provide full code of your action class.
Here is my current code:
Do you have a simple example to show the different process?
If you invoke your action on selected folder/directory you can obtain it from event via com.intellij.openapi.actionSystem.LangDataKeys.IDE_VIEW.getData(e.getDataContext()).getOrChooseDirectory()
After that you can follow the steps that was described, please try this approach.
Thank you but I'm still stuck :/
I can create an empty file with the PSI directory but I can't create a file from a psi. I have an error Cannot copy non-physical file, but how to convert a PSI file to a physical file?
If someone can give me a full example how to rename class name to my query.php file and write it into the PSI Directory I would be greatful because I can find a simple example.
Thank you.