package name.admitriev.jhelper.generation; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.jetbrains.cidr.lang.psi.OCCppNamespace; import com.jetbrains.cidr.lang.psi.OCDeclaration; import com.jetbrains.cidr.lang.psi.OCDeclarator; import com.jetbrains.cidr.lang.psi.OCElement; import com.jetbrains.cidr.lang.psi.OCFunctionDefinition; import com.jetbrains.cidr.lang.psi.OCStructLike; import com.jetbrains.cidr.lang.psi.OCTypeElement; import com.jetbrains.cidr.lang.psi.impl.OCDefineDirectiveImpl; import com.jetbrains.cidr.lang.psi.visitors.OCVisitor; import java.util.Collection; public class DeletionMarkingVisitor extends OCVisitor { private final Collection<PsiElement> toDelete; private SearchScope searchScope; public DeletionMarkingVisitor(Collection<PsiElement> toDelete, SearchScope searchScope) { //noinspection AssignmentToCollectionOrArrayFieldFromParameter this.toDelete = toDelete; this.searchScope = searchScope; } private static boolean isParentFor(OCElement potentialParent, PsiElement potentialChild) { while (potentialChild != null) { //noinspection ObjectEquality if (potentialChild == potentialParent) { return true; } potentialChild = potentialChild.getParent(); } return false; } @Override public void visitFunctionDefinition(OCFunctionDefinition functionDefinition) { String name = functionDefinition.getName(); if ("main".equals(name)) { return; } if (name != null && name.startsWith("operator")) { // To workaround a fact that no usages found for operators return; } super.visitFunctionDefinition(functionDefinition); } private void removeIfNoReference(OCElement element) { for (PsiReference reference : ReferencesSearch.search(element, searchScope)) { PsiElement referenceElement = reference.getElement(); if (!isParentFor(element, referenceElement)) { return; } } toDelete.add(element); } @Override public void visitNamespace(OCCppNamespace namespace) { if (namespace.getChildren().length == 0) { toDelete.add(namespace); } else { namespace.acceptChildren(this); } } @Override public void visitDefineDirective(OCDefineDirectiveImpl directive) { removeIfNoReference(directive); } @Override public void visitDeclarator(OCDeclarator declarator) { removeIfNoReference(declarator); } @Override public void visitStructLike(OCStructLike structLike) { removeIfNoReference(structLike); structLike.acceptChildren(this); } @Override public void visitTypeElement(OCTypeElement typeElement) { typeElement.acceptChildren(this); } @Override public void visitDeclaration(OCDeclaration declaration) { declaration.acceptChildren(this); } }