Search in sources :

Example 1 with PsiMethodPattern

use of com.intellij.patterns.PsiMethodPattern in project intellij-community by JetBrains.

the class IconsReferencesContributor method registerReferenceProviders.

@Override
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
    final PsiJavaElementPattern.Capture<PsiLiteralExpression> presentationAnno = literalExpression().annotationParam("com.intellij.ide.presentation.Presentation", "icon");
    registrar.registerReferenceProvider(presentationAnno, new PsiReferenceProvider() {

        @NotNull
        @Override
        public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
            if (!PsiUtil.isPluginProject(element.getProject()))
                return PsiReference.EMPTY_ARRAY;
            return new PsiReference[] { new PsiReferenceBase<PsiElement>(element, true) {

                @Override
                public PsiElement resolve() {
                    String value = (String) ((PsiLiteralExpression) element).getValue();
                    if (value != null) {
                        List<String> path = StringUtil.split(value, ".");
                        if (path.size() > 1 && path.get(0).endsWith("Icons")) {
                            Project project = element.getProject();
                            PsiClass cur = findIconClass(project, path.get(0));
                            if (cur == null) {
                                return null;
                            }
                            for (int i = 1; i < path.size() - 1; i++) {
                                cur = cur.findInnerClassByName(path.get(i), false);
                                if (cur == null) {
                                    return null;
                                }
                            }
                            return cur.findFieldByName(path.get(path.size() - 1), false);
                        }
                    }
                    return null;
                }

                @Override
                public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
                    PsiElement field = resolve();
                    if (field instanceof PsiField) {
                        String fqn = ((PsiField) field).getContainingClass().getQualifiedName();
                        if (fqn.startsWith("com.intellij.icons.")) {
                            return replace(newElementName, fqn, "com.intellij.icons.", element);
                        }
                        if (fqn.startsWith("icons.")) {
                            return replace(newElementName, fqn, "icons.", element);
                        }
                    }
                    return super.handleElementRename(newElementName);
                }

                @Override
                public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
                    if (element instanceof PsiField) {
                        String fqn = ((PsiField) element).getContainingClass().getQualifiedName();
                        String newElementName = ((PsiField) element).getName();
                        if (fqn.startsWith("com.intellij.icons.")) {
                            return replace(newElementName, fqn, "com.intellij.icons.", getElement());
                        }
                        if (fqn.startsWith("icons.")) {
                            return replace(newElementName, fqn, "icons.", getElement());
                        }
                    }
                    return super.bindToElement(element);
                }

                private PsiElement replace(String newElementName, String fqn, String pckg, PsiElement container) {
                    String newValue = "\"" + fqn.substring(pckg.length()) + "." + newElementName + "\"";
                    return getElement().replace(JavaPsiFacade.getElementFactory(container.getProject()).createExpressionFromText(newValue, container.getParent()));
                }

                @NotNull
                @Override
                public Object[] getVariants() {
                    return EMPTY_ARRAY;
                }
            } };
        }
    });
    final PsiMethodPattern method = psiMethod().withName("findIcon", "getIcon").definedInClass(IconLoader.class.getName());
    final PsiJavaElementPattern.Capture<PsiLiteralExpression> findGetIconPattern = literalExpression().and(psiExpression().methodCallParameter(0, method));
    registrar.registerReferenceProvider(findGetIconPattern, new PsiReferenceProvider() {

        @NotNull
        @Override
        public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
            if (!PsiUtil.isIdeaProject(element.getProject()))
                return PsiReference.EMPTY_ARRAY;
            return new FileReferenceSet(element) {

                @Override
                protected Collection<PsiFileSystemItem> getExtraContexts() {
                    final Module icons = ModuleManager.getInstance(element.getProject()).findModuleByName("icons");
                    if (icons != null) {
                        final ArrayList<PsiFileSystemItem> result = new ArrayList<>();
                        final VirtualFile[] roots = ModuleRootManager.getInstance(icons).getSourceRoots();
                        final PsiManager psiManager = element.getManager();
                        for (VirtualFile root : roots) {
                            final PsiDirectory directory = psiManager.findDirectory(root);
                            if (directory != null) {
                                result.add(directory);
                            }
                        }
                        return result;
                    }
                    return super.getExtraContexts();
                }
            }.getAllReferences();
        }
    });
    registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withLocalName("icon"), new PsiReferenceProvider() {

        @NotNull
        @Override
        public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
            if (!PsiUtil.isPluginProject(element.getProject()) || !DescriptorUtil.isPluginXml(element.getContainingFile())) {
                return PsiReference.EMPTY_ARRAY;
            }
            return new PsiReference[] { new PsiReferenceBase<PsiElement>(element, true) {

                @Override
                public PsiElement resolve() {
                    String value = ((XmlAttributeValue) element).getValue();
                    if (value.startsWith("/")) {
                        FileReference lastRef = new FileReferenceSet(element).getLastReference();
                        return lastRef != null ? lastRef.resolve() : null;
                    }
                    List<String> path = StringUtil.split(value, ".");
                    if (path.size() > 1 && path.get(0).endsWith("Icons")) {
                        Project project = element.getProject();
                        PsiClass cur = findIconClass(project, path.get(0));
                        if (cur == null)
                            return null;
                        for (int i = 1; i < path.size() - 1; i++) {
                            cur = cur.findInnerClassByName(path.get(i), false);
                            if (cur == null)
                                return null;
                        }
                        return cur.findFieldByName(path.get(path.size() - 1), false);
                    }
                    return null;
                }

                @Override
                public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
                    PsiElement element = resolve();
                    if (element instanceof PsiFile) {
                        FileReference lastRef = new FileReferenceSet(element).getLastReference();
                        return lastRef.handleElementRename(newElementName);
                    }
                    if (element instanceof PsiField) {
                        String fqn = ((PsiField) element).getContainingClass().getQualifiedName();
                        if (fqn.startsWith("com.intellij.icons.")) {
                            return replace(fqn, newElementName, "com.intellij.icons.");
                        }
                        if (fqn.startsWith("icons.")) {
                            return replace(fqn, newElementName, "icons.");
                        }
                    }
                    return super.handleElementRename(newElementName);
                }

                @Override
                public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
                    if (element instanceof PsiFile) {
                        FileReference lastRef = new FileReferenceSet(element).getLastReference();
                        return lastRef.bindToElement(element);
                    }
                    if (element instanceof PsiField) {
                        String fqn = ((PsiField) element).getContainingClass().getQualifiedName();
                        String newName = ((PsiField) element).getName();
                        if (fqn.startsWith("com.intellij.icons.")) {
                            return replace(fqn, newName, "com.intellij.icons.");
                        }
                        if (fqn.startsWith("icons.")) {
                            return replace(fqn, newName, "icons.");
                        }
                    }
                    return super.bindToElement(element);
                }

                private PsiElement replace(String fqn, String newName, String pckg) {
                    XmlAttribute parent = (XmlAttribute) getElement().getParent();
                    parent.setValue(fqn.substring(pckg.length()) + "." + newName);
                    return parent.getValueElement();
                }

                @NotNull
                @Override
                public Object[] getVariants() {
                    return EMPTY_ARRAY;
                }
            } };
        }
    });
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) ProcessingContext(com.intellij.util.ProcessingContext) XmlAttribute(com.intellij.psi.xml.XmlAttribute) ArrayList(java.util.ArrayList) NotNull(org.jetbrains.annotations.NotNull) ArrayList(java.util.ArrayList) List(java.util.List) FileReferenceSet(com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet) PsiMethodPattern(com.intellij.patterns.PsiMethodPattern) Project(com.intellij.openapi.project.Project) PsiJavaElementPattern(com.intellij.patterns.PsiJavaElementPattern) IncorrectOperationException(com.intellij.util.IncorrectOperationException) Module(com.intellij.openapi.module.Module) FileReference(com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference) PsiFileReference(com.intellij.psi.impl.source.resolve.reference.impl.providers.PsiFileReference) IconLoader(com.intellij.openapi.util.IconLoader)

Aggregations

Module (com.intellij.openapi.module.Module)1 Project (com.intellij.openapi.project.Project)1 IconLoader (com.intellij.openapi.util.IconLoader)1 VirtualFile (com.intellij.openapi.vfs.VirtualFile)1 PsiJavaElementPattern (com.intellij.patterns.PsiJavaElementPattern)1 PsiMethodPattern (com.intellij.patterns.PsiMethodPattern)1 FileReference (com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference)1 FileReferenceSet (com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet)1 PsiFileReference (com.intellij.psi.impl.source.resolve.reference.impl.providers.PsiFileReference)1 XmlAttribute (com.intellij.psi.xml.XmlAttribute)1 IncorrectOperationException (com.intellij.util.IncorrectOperationException)1 ProcessingContext (com.intellij.util.ProcessingContext)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 NotNull (org.jetbrains.annotations.NotNull)1