Detect removal of PsiElement

Answered

I have an Annotator, that displays custom warnings for import statements. It looks something like this:

@Override
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
if (element instanceof PsiImportStatement) {
...
TextRange range = new TextRange(element.getTextRange().getStartOffset() +
IMPORT_LITERAL_CHARACTER_COUNT_INCLUDING_WHITESPACE, element.getTextRange().getEndOffset());
holder.createWarningAnnotation(range, VIOLATION_MSG);
viewController.showLayerViolation(ruleService.getLayerForPackage(importLiteral));
}
}
}

When a warning is detected by the annotator a seperate view displays information related to the warning (see last line in code example).
Now when the import statement is removed I would like to update my view again.
I could not find a good solution to monitor the deletion of one of the import statements that have my custom warning on it.
I have already tried using PsiTreeChangeListeners childRemoved method, but it triggered very often and it seemed, that it did not cover all cases where an import statement was removed.
Is there any better solution to this?

Thanks,

Michael

0
3 comments

I believe that you should use `PsiTreeChangeListener` and update(re-validate) your view on each change, not only removal. Check if related psi element is still valid and remove notification if it's not. Next annotator/inspection pass will update panel with new warnings.

Also, see `com.intellij.psi.SmartPsiElementPointer`

1
Avatar
Permanently deleted user

Thank you for the quick response !
I will try using SmartPsiElementPointer to keep a reference to my psi import statements und re-validate them on each change triggered by PsiTreeChangeListener.
I will post my code and findings here afterwards.

0
Avatar
Permanently deleted user

I Could fix my problem by storing references to my psi elements using `SmartPsiElementPointer ` and validating if the referenced elements still exist each time `childrenChanged` is triggered on `PsiTreeChangeListener`.

It looks something like this:

The Annotator:

@Override
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
PsiFile containingFile = element.getContainingFile();
if (containingFile instanceof PsiJavaFile && element instanceof PsiImportStatement) {
...
if (elementFulfillsSomeCriteria) {
SmartPsiElementPointer violationElementPointer = smartPointerManager.createSmartPsiElementPointer(violationElement);
violationService.addViolation(violationElementPointer);
}
}
}

The PsiTreeChangeListener:

@Override
public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
violationService.validateViolations();
}

Thanks for your Help Alexandr!

0

Please sign in to leave a comment.