How to implement a PsiTreeChangeListener to Track Changes in PsiClass, PsiMethod, and PsiField Elements

Answered

I need to implement a PsiTreeChangedListener to maintain an AST (Abstract Syntax Tree) that I've created. I need to be able to retrieve the elements whenever a PsiClass, PsiMethod, or PsiField is added, removed, or renamed.

Currently, I'm facing an issue with handling the renaming events for PsiClass, PsiMethod, and PsiField. For example, if there's a variable named int a in a class, and I rename it to int aaa, I don't receive an event indicating this change.

 

public class MyPsiTreeChangedListener implements PsiTreeChangeListener {
    private final MyLogger log = MyLogger.getLogger(CjqPsiTreeChangedListener.class);
    private Project project;

    public MyPsiTreeChangedListener(Project project) {
        System.out.println("Psi Tree Changed Listener init");
        this.project = project;
    }


    private void dealWithElement(@NotNull PsiTreeChangeEvent event, String logInfo_PsiAction) {
        PsiElement element = event.getChild();

        if (element instanceof PsiClass) {
            PsiClass psiClass = (PsiClass) element;
            log.info(logInfo_PsiAction+": PsiMethod: " + psiClass.getName());
        } else if (element instanceof PsiMethod) {
            PsiMethod psiMethod = (PsiMethod) element;
            log.info(logInfo_PsiAction+": PsiMethod: " + psiMethod.getName());
        } else if (element instanceof PsiField) {
            PsiField psiField = (PsiField) element;
            log.info(logInfo_PsiAction+": PsiField: " + psiField.getName());
        }
    }

    @Override
    public void beforeChildAddition(@NotNull PsiTreeChangeEvent event) {
    }

    @Override
    public void beforeChildRemoval(@NotNull PsiTreeChangeEvent event) {
    }

    @Override
    public void beforeChildReplacement(@NotNull PsiTreeChangeEvent event) {
    }

    @Override
    public void beforeChildMovement(@NotNull PsiTreeChangeEvent event) {
    }

    @Override
    public void beforeChildrenChange(@NotNull PsiTreeChangeEvent event) {
    }

    @Override
    public void beforePropertyChange(@NotNull PsiTreeChangeEvent event) {
    }

    @Override
    public void childAdded(@NotNull PsiTreeChangeEvent event) {
        dealWithElement(event, "childAdded:");
    }

    @Override
    public void childRemoved(@NotNull PsiTreeChangeEvent event) {
        dealWithElement(event,"childRemoved:");
    }

    @Override
    public void childReplaced(@NotNull PsiTreeChangeEvent event) {
        dealWithElement(event, "childReplaced:");
    }

    @Override
    public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
    }

    @Override
    public void childMoved(@NotNull PsiTreeChangeEvent event) {
    }

    @Override
    public void propertyChanged(@NotNull PsiTreeChangeEvent event) {
    }

}
0
2 comments

Meanwhile, I would also like to inquire about the specific scenarios triggering 'propertyChanged' events.

0

Hi,

I tried to reproduce it, and it works.

I registered the listener, run a plugin, created a test class:

public class Test {
    int a;
}

After renaming it to aaa, I get the result printed:

childReplaced:: PsiField: a

0

Please sign in to leave a comment.