How to use PsiExpressionList

The PsiExpressionList class, as I understand it, keeps a list of PSI expressions. How am I using PsiExpressionList incorrectly?

I am trying to keep track of a set of statements that I will replace with a for loop that has those same statements inside its code block (codeBlock) by eventually calling toReplace.replace(forLoop); after I have built up my toReplace list as well as the codeBlock for the for loop and put it into forLoop.

I am able to insert expressionStatement (which is a PsiExpressionStatement) into the code block just fine using my helper method insertExpressionIntoCodeBlock, but when I try to insert expressionStatement to the PsiExpressionList toReplace using the built-in add function, it fails.

// List of lines of code to replace
PsiExpressionList toReplace = new PsiExpressionListImpl();

// Insert the expression statement (line) into the code block
PsiElement codeBlock = factory.createCodeBlock();
insertExpressionIntoCodeBlock(expressionStatement, codeBlock);

// Add the expression statement (line) to the list of replace-ables
toReplace.add(expressionStatement);



From the last line in this code snippet (line 101 in my code -- ConvertElementToCollection.java), I am getting a couple of errors including an Illegal argument exception. I have attached my stack trace, as well as photos of the debugger info for toReplace and expressionStatement right before the crash.



Attachment(s):
toReplace.png
expressionStatement.png
stack_trace.txt.zip
4 comments
Comment actions Permalink

A PsiExpressionList is not intended for you to store arbitrary lists of PSI expressions. It's intended to be used to represent language constructs where the grammar of the language has a list of PSI expressions. If you want to store a list of PSI elements that your code is working with, use a regular Java collection.

(Generally speaking, if you find yourself creating an instance of a class that has a name starting with "Psi" and ending with "Impl", you're almost certainly doing something wrong.)

Also note that you can't freely mix expressions and statements. A PsiExpressionStatement is a statement that holds an expression; it is not an expression itself.

0
Comment actions Permalink

Thanks for the clarification. That still leaves the question, though, of how to replace a set of statements. Do I have to delete them individually? From the following code, if I call replace on one of the elements, the other 3 will still be there. And if I add them to a Java collection, I can't call replace on them because a collection is not a PsiElement.

Original:

 
void start (Car car) {
    car.start();
    car.accelerate();
    car.decelerate();
    car.stop();
}


After replacing statement 1 with the for loop, for example.

 
void start (List<Car> cars) {
    for (Car car : cars) {
        car.start();
        car.accelerate();
        car.decelerate();
        car.stop();
    }
    car.accelerate();
    car.decelerate();
    car.stop();
}


Is there a way instead to move PsiElements? So I wouldn't have to delete/replace them?

0
Comment actions Permalink

There is no operation "replace this set of elements with this other set of elements". You need to process each element individually.

0
Comment actions Permalink

Thanks. Is there a way to move individual elements in one step? Or is the only way to do that by adding the element to the new location and deleting it from the old location?

0

Please sign in to leave a comment.