package com.cedricziel.idea.typo3.index.php; import com.cedricziel.idea.typo3.index.externalizer.ObjectStreamDataExternalizer; import com.intellij.openapi.project.Project; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiRecursiveElementVisitor; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.EnumeratorStringDescriptor; import com.intellij.util.io.KeyDescriptor; import com.jetbrains.php.lang.psi.elements.ClassReference; import com.jetbrains.php.lang.psi.elements.PhpClass; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; public class LegacyClassesForIDEIndex extends FileBasedIndexExtension<String, String> { public static ID<String, String> KEY = ID.create("com.cedricziel.idea.typo3.index.php.legacy_classes"); private final KeyDescriptor<String> myKeyDescriptor = new EnumeratorStringDescriptor(); public static boolean isLegacyClass(@NotNull Project project, @NotNull String fqn) { return FileBasedIndex.getInstance().getAllKeys(LegacyClassesForIDEIndex.KEY, project).contains(fqn); } @Nullable public static String findReplacementClass(@NotNull Project project, @NotNull String fqn) { List<String> values = FileBasedIndex.getInstance().getValues(KEY, fqn, GlobalSearchScope.allScope(project)); if (values.size() > 0) { return values.iterator().next(); } return null; } @NotNull @Override public ID<String, String> getName() { return KEY; } @NotNull @Override public DataIndexer<String, String, FileContent> getIndexer() { return inputData -> { Map<String, String> map = new THashMap<>(); LegacyClassesRecursiveVisitor visitor = new LegacyClassesRecursiveVisitor(); visitor.visitElement(inputData.getPsiFile()); visitor.getMap().forEach(map::put); return map; }; } @NotNull @Override public KeyDescriptor<String> getKeyDescriptor() { return myKeyDescriptor; } @NotNull @Override public DataExternalizer<String> getValueExternalizer() { return new ObjectStreamDataExternalizer<>(); } @Override public int getVersion() { return 0; } @NotNull @Override public FileBasedIndex.InputFilter getInputFilter() { return file -> file.getName().equals("LegacyClassesForIde.php"); } @Override public boolean dependsOnFileContent() { return true; } private static class LegacyClassesRecursiveVisitor extends PsiRecursiveElementVisitor { private final Map<String, String> map; LegacyClassesRecursiveVisitor() { map = new THashMap<>(); } public Map<String, String> getMap() { return map; } @Override public void visitElement(@NotNull PsiElement element) { if (!PlatformPatterns.psiElement(PhpClass.class).accepts(element)) { super.visitElement(element); return; } PhpClass phpClass = (PhpClass) element; String fqn = phpClass.getFQN(); String superFqn = null; if (!phpClass.isInterface()) { superFqn = phpClass.getSuperFQN(); } else { List<ClassReference> referenceElements = phpClass.getExtendsList().getReferenceElements(); for (ClassReference cr : referenceElements) { superFqn = cr.getFQN(); } } if (superFqn != null) { map.put(fqn, superFqn); } super.visitElement(element); } } }