Getting the PsiElement at the caret

When extending AnAction class for a custom refactoring plugin, how do we get the PsiElement at the caret?

We are able to get the declaration of the PsiElement by using:

 
public class InsertCheckForNullAction extends AnAction {
 
     public void actionPerformed(AnActionEvent e) {
     Project project = e.getData(PlatformDataKeys.PROJECT);
     PsiElement element = e.getData(LangDataKeys.PSI_ELEMENT);


We create a PsiIfStatement ifStatement and then try to insert it before element using the code below:

PsiIfStatement ifStatement= (PsiIfStatement)factory
     .createStatementFromText("if(a){\nst;\n}", null);

PsiExpression condition = ifStatement.getCondition();
     if (condition != null) {
          condition.replace(expr);
     }
element
.addBefore(ifStatement, element.getFirstChild());


However, the ifStatement is added before the declaration corresponding to element instead of before the place where the carat is (at the variable corresponding to element within the code).

4 comments
Comment actions Permalink

Hi,

 
'element.addBefore(ifStatement, element.getFirstChild());'
means that ifStatement would be inserted inside 'element'. It looks like you need to find element's container.

You may look e.g. at com.intellij.codeInspection.SurroundWithIfFix which also performs this step.

Anna
0
Comment actions Permalink

Thank you Anna. This didn't actually solve the problem we were asking about, but it solved another problem that we were having. Before, our if statement was added before the variable, and now it is added around the variable. :)

We are still having the issue where when we invoke our refactoring from this state:

 
public class PersonClass {
    private String name;

    public PersonClass(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name<caret> = name;
    }
}


we get this as a result:

public class PersonClass {
 
    if (name != null) {
        private String name;
    }
 
    
 
    public PersonClass(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name<caret> = name;
    }
}


in which it replaces the declaration with a syntactically incorrect check for null around the declaration.

What we really want is this:

public class PersonClass {
    private String name;
 
    
    public PersonClass(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (name != null) {
            this.name<caret> = name;
        }
}
}
0
Comment actions Permalink

if you use file.findElementAt(editor.getCaretModel().getOffset()) you'll get identifier under caret. File and editor can be retrieved from data context as you already do for psi element.
Anna

0
Comment actions Permalink

Thanks! That's exactly what we needed.

0

Please sign in to leave a comment.