Merge remote-tracking branch 'origin/master'
[idea/community.git] / platform / lang-impl / src / com / intellij / codeInspection / ui / InspectionResultsViewComparator.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * Created by IntelliJ IDEA.
19  * User: max
20  * Date: Nov 23, 2001
21  * Time: 10:31:03 PM
22  * To change template for new class use
23  * Code Style | Class Templates options (Tools | IDE Options).
24  */
25 package com.intellij.codeInspection.ui;
26
27 import com.intellij.codeInsight.daemon.impl.SeverityRegistrar;
28 import com.intellij.codeInspection.CommonProblemDescriptor;
29 import com.intellij.codeInspection.ProblemDescriptor;
30 import com.intellij.codeInspection.offline.OfflineProblemDescriptor;
31 import com.intellij.codeInspection.offlineViewer.OfflineRefElementNode;
32 import com.intellij.codeInspection.reference.RefElement;
33 import com.intellij.codeInspection.reference.RefEntity;
34 import com.intellij.openapi.diagnostic.Logger;
35 import com.intellij.openapi.util.Comparing;
36 import com.intellij.openapi.util.text.StringUtil;
37 import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionsConfigTreeComparator;
38 import com.intellij.psi.PsiElement;
39 import com.intellij.psi.PsiNamedElement;
40 import com.intellij.psi.PsiQualifiedNamedElement;
41 import com.intellij.psi.util.PsiUtilCore;
42
43 import java.util.Comparator;
44
45 public class InspectionResultsViewComparator implements Comparator {
46   private static final Logger LOG = Logger.getInstance(InspectionResultsViewComparator.class);
47
48   public boolean areEqual(Object o1, Object o2) {
49     return o1.getClass().equals(o2.getClass()) && compare(o1, o2) == 0;
50   }
51
52   @Override
53   public int compare(Object o1, Object o2) {
54     InspectionTreeNode node1 = (InspectionTreeNode)o1;
55     InspectionTreeNode node2 = (InspectionTreeNode)o2;
56
57     if (node1 instanceof InspectionSeverityGroupNode && node2 instanceof InspectionSeverityGroupNode) {
58       final InspectionSeverityGroupNode groupNode1 = (InspectionSeverityGroupNode)node1;
59       final InspectionSeverityGroupNode groupNode2 = (InspectionSeverityGroupNode)node2;
60       return -SeverityRegistrar.getSeverityRegistrar(groupNode1.getProject()).compare(groupNode1.getSeverityLevel().getSeverity(), groupNode2.getSeverityLevel().getSeverity());
61     }
62     if (node1 instanceof InspectionSeverityGroupNode) return -1;
63     if (node2 instanceof InspectionSeverityGroupNode) return 1;
64
65     if (node1 instanceof InspectionGroupNode && node2 instanceof InspectionGroupNode) {
66       return ((InspectionGroupNode)node1).getGroupTitle().compareToIgnoreCase(((InspectionGroupNode)node2).getGroupTitle());
67     }
68     if (node1 instanceof InspectionGroupNode) return -1;
69     if (node2 instanceof InspectionGroupNode) return 1;
70
71     if (node1 instanceof InspectionNode && node2 instanceof InspectionNode)
72       return InspectionsConfigTreeComparator.getDisplayTextToSort(node1.toString())
73         .compareToIgnoreCase(InspectionsConfigTreeComparator.getDisplayTextToSort(node2.toString()));
74     if (node1 instanceof InspectionNode) return -1;
75     if (node2 instanceof InspectionNode) return 1;
76
77     if (node1 instanceof InspectionModuleNode && node2 instanceof InspectionModuleNode) {
78       return Comparing.compare(node1.toString(), node2.toString());
79     }
80     if (node1 instanceof InspectionModuleNode) return -1;
81     if (node2 instanceof InspectionModuleNode) return 1;
82
83     if (node1 instanceof InspectionPackageNode && node2 instanceof InspectionPackageNode) {
84       return ((InspectionPackageNode)node1).getPackageName().compareToIgnoreCase(((InspectionPackageNode)node2).getPackageName());
85     }
86     if (node1 instanceof InspectionPackageNode) return -1;
87     if (node2 instanceof InspectionPackageNode) return 1;
88
89     if (node1 instanceof OfflineRefElementNode && node2 instanceof OfflineRefElementNode) {
90       final Object userObject1 = ((OfflineRefElementNode)node1).getOfflineDescriptor();
91       final Object userObject2 = ((OfflineRefElementNode)node2).getOfflineDescriptor();
92       final OfflineProblemDescriptor descriptor1 = (OfflineProblemDescriptor)userObject1;
93       final OfflineProblemDescriptor descriptor2 = (OfflineProblemDescriptor)userObject2;
94       if (descriptor1.getLine() != descriptor2.getLine()) return descriptor1.getLine() - descriptor2.getLine();
95       return descriptor1.getFQName().compareToIgnoreCase(descriptor2.getFQName());
96     }
97
98     if (node1 instanceof RefElementNode && node2 instanceof RefElementNode){   //sort by filename and inside file by start offset
99       return compareEntities(((RefElementNode)node1).getElement(), ((RefElementNode)node2).getElement());
100     }
101     if (node1 instanceof ProblemDescriptionNode && node2 instanceof ProblemDescriptionNode) {
102       final CommonProblemDescriptor descriptor1 = ((ProblemDescriptionNode)node1).getDescriptor();
103       final CommonProblemDescriptor descriptor2 = ((ProblemDescriptionNode)node2).getDescriptor();
104       if (descriptor1 instanceof ProblemDescriptor && descriptor2 instanceof ProblemDescriptor) {
105         //TODO: Do not materialise lazy pointers
106         return ((ProblemDescriptor)descriptor1).getLineNumber() - ((ProblemDescriptor)descriptor2).getLineNumber();
107       }
108       if (descriptor1 != null && descriptor2 != null) {
109         return descriptor1.getDescriptionTemplate().compareToIgnoreCase(descriptor2.getDescriptionTemplate());
110       }
111       if (descriptor1 == null) return descriptor2 == null ? 0 : -1;
112       return 1;
113     }
114
115     if (node1 instanceof RefElementNode && node2 instanceof ProblemDescriptionNode) {
116       final CommonProblemDescriptor descriptor = ((ProblemDescriptionNode)node2).getDescriptor();
117       if (descriptor instanceof ProblemDescriptor) {
118         return compareEntity(((RefElementNode)node1).getElement(), ((ProblemDescriptor)descriptor).getPsiElement());
119       }
120       return compareEntities(((RefElementNode)node1).getElement(), ((ProblemDescriptionNode)node2).getElement());
121     }
122
123     if (node2 instanceof RefElementNode && node1 instanceof ProblemDescriptionNode) {
124       final CommonProblemDescriptor descriptor = ((ProblemDescriptionNode)node1).getDescriptor();
125       if (descriptor instanceof ProblemDescriptor) {
126         return -compareEntity(((RefElementNode)node2).getElement(), ((ProblemDescriptor)descriptor).getPsiElement());
127       }
128       return -compareEntities(((RefElementNode)node2).getElement(), ((ProblemDescriptionNode)node1).getElement());
129     }
130     if (node1 instanceof InspectionRootNode && node2 instanceof InspectionRootNode) {
131       //TODO Dmitry Batkovich: optimization, because only one root node is existed
132       return 0;
133     }
134
135     LOG.error("node1: " + node1 + ", node2: " + node2);
136     return 0;
137   }
138
139   private static int compareEntity(final RefEntity entity, final PsiElement element) {
140     if (entity instanceof RefElement) {
141       final PsiElement psiElement = ((RefElement)entity).getElement();
142       if (psiElement != null && element != null) {
143         return PsiUtilCore.compareElementsByPosition(psiElement, element);
144       }
145       if (element == null) return psiElement == null ? 0 : 1;
146     }
147     if (element instanceof PsiQualifiedNamedElement) {
148       return StringUtil.compare(entity.getQualifiedName(), ((PsiQualifiedNamedElement)element).getQualifiedName(), true);
149     }
150     if (element instanceof PsiNamedElement) {
151       return StringUtil.compare(entity.getName(), ((PsiNamedElement)element).getName(), true);
152     }
153     return -1;
154   }
155
156   private static int compareEntities(final RefEntity entity1, final RefEntity entity2) {
157     if (entity1 instanceof RefElement && entity2 instanceof RefElement) {
158       final int positionComparing = PsiUtilCore.compareElementsByPosition(((RefElement)entity1).getElement(), ((RefElement)entity2).getElement());
159       if (positionComparing != 0) {
160         return positionComparing;
161       }
162     }
163     if (entity1 != null && entity2 != null) {
164       final int nameComparing = entity1.getName().compareToIgnoreCase(entity2.getName());
165       if (nameComparing != 0) {
166         return nameComparing;
167       }
168       return entity1.getQualifiedName().compareToIgnoreCase(entity2.getQualifiedName());
169     }
170     if (entity1 != null) return -1;
171     return entity2 != null ? 1 : 0;
172   }
173
174   private static class InspectionResultsViewComparatorHolder {
175     private static final InspectionResultsViewComparator ourInstance = new InspectionResultsViewComparator();
176   }
177
178   public static InspectionResultsViewComparator getInstance() {
179     return InspectionResultsViewComparatorHolder.ourInstance;
180   }
181 }