6b049b7d6ee5656e0b834d23070117c2aacfa7af
[idea/community.git] / java / java-tests / testSrc / com / intellij / codeInspection / ex / InspectionProfileTest.java
1 /*
2  * Copyright 2000-2016 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 package com.intellij.codeInspection.ex;
17
18 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
19 import com.intellij.codeInspection.InspectionManager;
20 import com.intellij.codeInspection.LocalInspectionEP;
21 import com.intellij.codeInspection.LocalInspectionTool;
22 import com.intellij.codeInspection.ModifiableModel;
23 import com.intellij.codeInspection.dataFlow.DataFlowInspection;
24 import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase;
25 import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
26 import com.intellij.openapi.util.JDOMUtil;
27 import com.intellij.openapi.util.WriteExternalException;
28 import com.intellij.profile.Profile;
29 import com.intellij.profile.codeInspection.InspectionProfileManager;
30 import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
31 import com.intellij.profile.codeInspection.ProjectInspectionProfileManager;
32 import com.intellij.profile.codeInspection.ui.header.InspectionToolsConfigurable;
33 import com.intellij.psi.PsiModifier;
34 import com.intellij.testFramework.LightIdeaTestCase;
35 import com.intellij.util.JdomKt;
36 import com.intellij.util.SmartList;
37 import org.jdom.Element;
38 import org.jdom.JDOMException;
39 import org.jetbrains.annotations.NotNull;
40
41 import java.io.IOException;
42 import java.util.ArrayList;
43 import java.util.Collections;
44 import java.util.List;
45
46 import static com.intellij.profile.ProfileEx.serializeProfile;
47 import static com.intellij.testFramework.PlatformTestUtil.assertElementsEqual;
48
49 /**
50  * @author Anna.Kozlova
51  * Date: 18-Aug-2006
52  */
53 public class InspectionProfileTest extends LightIdeaTestCase {
54   private static final String PROFILE = "ToConvert";
55
56   @Override
57   protected void setUp() throws Exception {
58     //noinspection AssignmentToStaticFieldFromInstanceMethod
59     InspectionProfileImpl.INIT_INSPECTIONS = true;
60     super.setUp();
61     InspectionToolRegistrar.getInstance().createTools();
62   }
63
64   @Override
65   protected void tearDown() throws Exception {
66     try {
67       //noinspection SuperTearDownInFinally
68       super.tearDown();
69     }
70     finally {
71       //noinspection AssignmentToStaticFieldFromInstanceMethod
72       InspectionProfileImpl.INIT_INSPECTIONS = false;
73       InspectionProfileManager.getInstance().deleteProfile(PROFILE);
74     }
75   }
76
77   public void testCopyProjectProfile() throws Exception {
78     final Element element = loadProfile();
79     final InspectionProfileImpl profile = createProfile();
80     profile.readExternal(element);
81     final ModifiableModel model = profile.getModifiableModel();
82     model.commit();
83     assertElementsEqual(element, serializeProfile(profile));
84   }
85
86   private static InspectionProfileImpl createProfile() {
87     return new InspectionProfileImpl(PROFILE, InspectionToolRegistrar.getInstance(), InspectionProfileManager.getInstance(), InspectionProfileImpl.getDefaultProfile(), null);
88   }
89   private static InspectionProfileImpl createProfile(@NotNull InspectionProfileImpl base) {
90     return new InspectionProfileImpl(PROFILE, InspectionToolRegistrar.getInstance(), InspectionProfileManager.getInstance(), base, null);
91   }
92
93   public void testSameNameSharedProfile() throws Exception {
94     InspectionProfileManager profileManager = InspectionProfileManager.getInstance();
95     InspectionProfileImpl localProfile = createProfile();
96     profileManager.updateProfile(localProfile);
97
98     ProjectInspectionProfileManager projectProfileManager = ProjectInspectionProfileManager.getInstanceImpl(getProject());
99     try {
100       //normally on open project profile wrappers are init for both managers
101       profileManager.updateProfile(localProfile);
102       InspectionProfileImpl profile = new InspectionProfileImpl(PROFILE, InspectionToolRegistrar.getInstance(), projectProfileManager,
103                                                                 InspectionProfileImpl.getDefaultProfile(), null);
104       projectProfileManager.updateProfile(profile);
105       projectProfileManager.setRootProfile(profile.getName());
106
107       assertTrue(projectProfileManager.getCurrentProfile() == profile);
108     }
109     finally {
110       projectProfileManager.deleteProfile(PROFILE);
111     }
112   }
113
114   public void testConvertOldProfile() throws Exception {
115     Element element = JDOMUtil.loadDocument("<inspections version=\"1.0\">\n" +
116                                             "  <option name=\"myName\" value=\"ToConvert\" />\n" +
117                                             "  <inspection_tool class=\"JavaDoc\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
118                                             "    <option name=\"TOP_LEVEL_CLASS_OPTIONS\">\n" +
119                                             "      <value>\n" +
120                                             "        <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
121                                             "        <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
122                                             "      </value>\n" +
123                                             "    </option>\n" +
124                                             "    <option name=\"INNER_CLASS_OPTIONS\">\n" +
125                                             "      <value>\n" +
126                                             "        <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
127                                             "        <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
128                                             "      </value>\n" +
129                                             "    </option>\n" +
130                                             "    <option name=\"METHOD_OPTIONS\">\n" +
131                                             "      <value>\n" +
132                                             "        <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
133                                             "        <option name=\"REQUIRED_TAGS\" value=\"@return@param@throws or @exception\" />\n" +
134                                             "      </value>\n" + "    </option>\n" +
135                                             "    <option name=\"FIELD_OPTIONS\">\n" +
136                                             "      <value>\n" +
137                                             "        <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
138                                             "        <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
139                                             "      </value>\n" +
140                                             "    </option>\n" +
141                                             "    <option name=\"IGNORE_DEPRECATED\" value=\"false\" />\n" +
142                                             "    <option name=\"IGNORE_JAVADOC_PERIOD\" value=\"false\" />\n" +
143                                             "    <option name=\"IGNORE_DUPLICATED_THROWS\" value=\"false\" />\n" +
144                                             "    <option name=\"IGNORE_POINT_TO_ITSELF\" value=\"false\" />\n" +
145                                             "    <option name=\"myAdditionalJavadocTags\" value=\"tag1,tag2 \" />\n" +
146                                             "  </inspection_tool>\n" +
147                                             "</inspections>").getRootElement();
148     InspectionProfileImpl profile = createProfile();
149     profile.readExternal(element);
150     ModifiableModel model = profile.getModifiableModel();
151     model.commit();
152
153     assertElementsEqual(loadProfile(), serializeProfile(profile));
154   }
155
156   private static Element loadProfile() throws IOException, JDOMException {
157     return JdomKt.loadElement("<profile version=\"1.0\">\n" +
158                        "  <option name=\"myName\" value=\"ToConvert\" />\n" +
159                        "  <inspection_tool class=\"JavaDoc\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
160                        "    <option name=\"TOP_LEVEL_CLASS_OPTIONS\">\n" +
161                        "      <value>\n" +
162                        "        <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
163                        "        <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
164                        "      </value>\n" +
165                        "    </option>\n" +
166                        "    <option name=\"INNER_CLASS_OPTIONS\">\n" +
167                        "      <value>\n" +
168                        "        <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
169                        "        <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
170                        "      </value>\n" +
171                        "    </option>\n" +
172                        "    <option name=\"METHOD_OPTIONS\">\n" +
173                        "      <value>\n" +
174                        "        <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
175                        "        <option name=\"REQUIRED_TAGS\" value=\"@return@param@throws or @exception\" />\n" +
176                        "      </value>\n" + "    </option>\n" +
177                        "    <option name=\"FIELD_OPTIONS\">\n" +
178                        "      <value>\n" +
179                        "        <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
180                        "        <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
181                        "      </value>\n" +
182                        "    </option>\n" +
183                        "    <option name=\"IGNORE_DEPRECATED\" value=\"false\" />\n" +
184                        "    <option name=\"IGNORE_JAVADOC_PERIOD\" value=\"false\" />\n" +
185                        "    <option name=\"IGNORE_DUPLICATED_THROWS\" value=\"false\" />\n" +
186                        "    <option name=\"IGNORE_POINT_TO_ITSELF\" value=\"false\" />\n" +
187                        "    <option name=\"myAdditionalJavadocTags\" value=\"tag1,tag2 \" />\n" +
188                        "  </inspection_tool>\n" +
189                        "</profile>");
190   }
191
192   public void testReloadProfileWithUnknownScopes() throws Exception {
193     final Element element = JdomKt.loadElement("<profile version=\"1.0\">\n" +
194                                                   "  <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
195                                                   "  <inspection_tool class=\"ArgNamesErrorsInspection\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"false\" />\n" +
196                                                   "  <inspection_tool class=\"ArgNamesWarningsInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\" />\n" +
197                                                   "  <inspection_tool class=\"AroundAdviceStyleInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\" />\n" +
198                                                   "  <inspection_tool class=\"DeclareParentsInspection\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"false\" />\n" +
199                                                   /*"  <inspection_tool class=\"ManifestDomInspection\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"false\" />\n" +*/
200                                                   "  <inspection_tool class=\"MissingAspectjAutoproxyInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\" />\n" +
201                                                   "  <inspection_tool class=\"UNUSED_IMPORT\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n" +
202                                                   "    <scope name=\"Unknown scope name\" level=\"WARNING\" enabled=\"true\" />\n" +
203                                                   "  </inspection_tool>\n" +
204                                                   "</profile>");
205     final InspectionProfileImpl profile = createProfile();
206     profile.readExternal(element);
207     final ModifiableModel model = profile.getModifiableModel();
208     model.commit();
209     assertElementsEqual(element, serializeProfile(profile));
210   }
211
212   public void testMergeUnusedDeclarationAndUnusedSymbol() throws Exception {
213     //no specific settings
214     final Element element = JdomKt.loadElement("<profile version=\"1.0\">\n" +
215                                                   "  <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
216                                                   "</profile>");
217     InspectionProfileImpl profile = createProfile(new InspectionProfileImpl("foo"));
218     profile.readExternal(element);
219     ModifiableModel model = profile.getModifiableModel();
220     model.commit();
221     assertElementsEqual(element, serializeProfile(profile));
222
223
224     //settings to merge
225     final Element unusedProfile = JdomKt.loadElement("<profile version=\"1.0\">\n" +
226                                                         "  <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
227                                                         "  <inspection_tool class=\"UNUSED_SYMBOL\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
228                                                         "      <option name=\"LOCAL_VARIABLE\" value=\"true\" />\n" +
229                                                         "      <option name=\"FIELD\" value=\"true\" />\n" +
230                                                         "      <option name=\"METHOD\" value=\"true\" />\n" +
231                                                         "      <option name=\"CLASS\" value=\"true\" />\n" +
232                                                         "      <option name=\"PARAMETER\" value=\"true\" />\n" +
233                                                         "      <option name=\"REPORT_PARAMETER_FOR_PUBLIC_METHODS\" value=\"false\" />\n" +
234                                                         "  </inspection_tool>\n" +
235                                                         "  <inspection_tool class=\"UnusedDeclaration\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
236                                                         "      <option name=\"ADD_MAINS_TO_ENTRIES\" value=\"true\" />\n" +
237                                                         "      <option name=\"ADD_APPLET_TO_ENTRIES\" value=\"true\" />\n" +
238                                                         "      <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
239                                                         "      <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"false\" />\n" +
240                                                         "   </inspection_tool>\n" +
241                                                         "</profile>");
242     profile.readExternal(unusedProfile);
243     model = profile.getModifiableModel();
244     model.commit();
245     assertEquals("<profile version=\"1.0\">\n" +
246                  "  <option name=\"myName\" value=\"ToConvert\" />\n" +
247                  "  <inspection_tool class=\"UNUSED_SYMBOL\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
248                  "    <option name=\"LOCAL_VARIABLE\" value=\"true\" />\n" +
249                  "    <option name=\"FIELD\" value=\"true\" />\n" +
250                  "    <option name=\"METHOD\" value=\"true\" />\n" +
251                  "    <option name=\"CLASS\" value=\"true\" />\n" +
252                  "    <option name=\"PARAMETER\" value=\"true\" />\n" +
253                  "    <option name=\"REPORT_PARAMETER_FOR_PUBLIC_METHODS\" value=\"false\" />\n" +
254                  "  </inspection_tool>\n" +
255                  "  <inspection_tool class=\"UnusedDeclaration\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
256                  "    <option name=\"ADD_MAINS_TO_ENTRIES\" value=\"true\" />\n" +
257                  "    <option name=\"ADD_APPLET_TO_ENTRIES\" value=\"true\" />\n" +
258                  "    <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
259                  "    <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"false\" />\n" +
260                  "  </inspection_tool>\n" +
261                  "</profile>", serialize(profile));
262
263     //make them default
264     profile = createProfile(new InspectionProfileImpl("foo"));
265     profile.readExternal(unusedProfile);
266     model = profile.getModifiableModel();
267     InspectionToolWrapper toolWrapper = ((InspectionProfileImpl)model).getInspectionTool("unused", getProject());
268     UnusedDeclarationInspectionBase tool = (UnusedDeclarationInspectionBase)toolWrapper.getTool();
269     tool.ADD_NONJAVA_TO_ENTRIES = true;
270     UnusedSymbolLocalInspectionBase inspectionTool = tool.getSharedLocalInspectionTool();
271     inspectionTool.setParameterVisibility(PsiModifier.PUBLIC);
272     model.commit();
273     String mergedText = "<profile version=\"1.0\">\n" +
274                         "  <option name=\"myName\" value=\"ToConvert\" />\n" +
275                         "  <inspection_tool class=\"UNUSED_SYMBOL\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
276                         "    <option name=\"LOCAL_VARIABLE\" value=\"true\" />\n" +
277                         "    <option name=\"FIELD\" value=\"true\" />\n" +
278                         "    <option name=\"METHOD\" value=\"true\" />\n" +
279                         "    <option name=\"CLASS\" value=\"true\" />\n" +
280                         "    <option name=\"PARAMETER\" value=\"true\" />\n" +
281                         "    <option name=\"REPORT_PARAMETER_FOR_PUBLIC_METHODS\" value=\"false\" />\n" +
282                         "  </inspection_tool>\n" +
283                         "  <inspection_tool class=\"UnusedDeclaration\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
284                         "    <option name=\"ADD_MAINS_TO_ENTRIES\" value=\"true\" />\n" +
285                         "    <option name=\"ADD_APPLET_TO_ENTRIES\" value=\"true\" />\n" +
286                         "    <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
287                         "    <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"false\" />\n" +
288                         "  </inspection_tool>\n" +
289                         "  <inspection_tool class=\"unusedMerged\" />\n" +
290                         "</profile>";
291     assertEquals(mergedText, serialize(profile));
292
293     Element toImportElement = serializeProfile(profile);
294     final InspectionProfileImpl importedProfile =
295       InspectionToolsConfigurable.importInspectionProfile(toImportElement, InspectionProfileManager.getInstance(), getProject(), null);
296
297     //check merged
298     Element mergedElement = JDOMUtil.loadDocument(mergedText).getRootElement();
299     profile = createProfile(new InspectionProfileImpl("foo"));
300     profile.readExternal(mergedElement);
301     model = profile.getModifiableModel();
302     model.commit();
303     assertElementsEqual(mergedElement, serializeProfile(profile));
304
305     assertElementsEqual(mergedElement, serializeProfile(importedProfile));
306   }
307
308   public void testStoredMemberVisibility() throws Exception {
309     InspectionProfileImpl profile = createProfile(new InspectionProfileImpl("foo"));
310     profile.readExternal(JDOMUtil.loadDocument("<profile version=\"1.0\">\n" +
311                                                "  <inspection_tool class=\"unused\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n" +
312                                                "    <option name=\"LOCAL_VARIABLE\" value=\"true\" />\n" +
313                                                "    <option name=\"FIELD\" value=\"true\" />\n" +
314                                                "    <option name=\"METHOD\" value=\"true\" />\n" +
315                                                "    <option name=\"CLASS\" value=\"true\" />\n" +
316                                                "    <option name=\"PARAMETER\" value=\"true\" />\n" +
317                                                "    <option name=\"REPORT_PARAMETER_FOR_PUBLIC_METHODS\" value=\"true\" />\n" +
318                                                "    <option name=\"ADD_MAINS_TO_ENTRIES\" value=\"true\" />\n" +
319                                                "    <option name=\"ADD_APPLET_TO_ENTRIES\" value=\"true\" />\n" +
320                                                "    <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
321                                                "    <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"false\" />\n" +
322                                                "  </inspection_tool>\n" +
323                                                "</profile>").getRootElement());
324     InspectionProfileImpl model = profile.getModifiableModel();
325     InspectionToolWrapper toolWrapper = model.getInspectionTool("unused", getProject());
326     UnusedDeclarationInspectionBase tool = (UnusedDeclarationInspectionBase)toolWrapper.getTool();
327     UnusedSymbolLocalInspectionBase inspectionTool = tool.getSharedLocalInspectionTool();
328     inspectionTool.setClassVisibility("none");
329     model.commit();
330     String mergedText = "<profile version=\"1.0\">\n" +
331                         "  <option name=\"myName\" value=\"ToConvert\" />\n" +
332                         "  <inspection_tool class=\"unused\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" inner_class=\"none\">\n" +
333                         "    <option name=\"LOCAL_VARIABLE\" value=\"true\" />\n" +
334                         "    <option name=\"FIELD\" value=\"true\" />\n" +
335                         "    <option name=\"METHOD\" value=\"true\" />\n" +
336                         "    <option name=\"CLASS\" value=\"false\" />\n" +
337                         "    <option name=\"PARAMETER\" value=\"true\" />\n" +
338                         "    <option name=\"REPORT_PARAMETER_FOR_PUBLIC_METHODS\" value=\"true\" />\n" +
339                         "    <option name=\"ADD_MAINS_TO_ENTRIES\" value=\"true\" />\n" +
340                         "    <option name=\"ADD_APPLET_TO_ENTRIES\" value=\"true\" />\n" +
341                         "    <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
342                         "    <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"false\" />\n" +
343                         "  </inspection_tool>\n" +
344                         "</profile>";
345     assertEquals(mergedText, serialize(profile));
346   }
347
348   public void testDisabledUnusedDeclarationWithoutChanges() throws Exception {
349     checkMergedNoChanges("<profile version=\"1.0\">\n" +
350                          "  <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
351                          "  <inspection_tool class=\"UnusedDeclaration\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
352                          "    <option name=\"ADD_MAINS_TO_ENTRIES\" value=\"true\" />\n" +
353                          "    <option name=\"ADD_APPLET_TO_ENTRIES\" value=\"true\" />\n" +
354                          "    <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
355                          "    <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"true\" />\n" +
356                          "  </inspection_tool>\n" +
357                          "</profile>");
358   }
359
360   public void testMergedMisspelledInspections() throws Exception {
361     checkMergedNoChanges("<profile version=\"1.0\">\n" +
362                          "  <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
363                          "  <inspection_tool class=\"MethodNamesDifferOnlyByCase\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
364                          "    <option name=\"ignoreIfMethodIsOverride\" value=\"false\" />\n" +
365                          "  </inspection_tool>\n" +
366                          "</profile>");
367     checkMergedNoChanges("<profile version=\"1.0\">\n" +
368                          "  <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
369                          "  <inspection_tool class=\"MethodNamesDifferOnlyByCase\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
370                          "    <option name=\"ignoreIfMethodIsOverride\" value=\"false\" />\n" +
371                          "  </inspection_tool>\n" +
372                          "  <inspection_tool class=\"MisspelledSetUp\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\" />\n" +
373                          "</profile>");
374   }
375
376   public void testDisabledUnusedDeclarationWithChanges() throws Exception {
377     checkMergedNoChanges("<profile version=\"1.0\">\n" +
378                          "  <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
379                          "  <inspection_tool class=\"UnusedDeclaration\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
380                          "    <option name=\"ADD_MAINS_TO_ENTRIES\" value=\"true\" />\n" +
381                          "    <option name=\"ADD_APPLET_TO_ENTRIES\" value=\"true\" />\n" +
382                          "    <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
383                          "    <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"false\" />\n" +
384                          "  </inspection_tool>\n" +
385                          "</profile>");
386   }
387
388   public void testEnabledUnusedDeclarationWithChanges() throws Exception {
389     checkMergedNoChanges("<profile version=\"1.0\">\n" +
390                          "  <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
391                          "  <inspection_tool class=\"UnusedDeclaration\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n" +
392                          "    <option name=\"ADD_MAINS_TO_ENTRIES\" value=\"true\" />\n" +
393                          "    <option name=\"ADD_APPLET_TO_ENTRIES\" value=\"true\" />\n" +
394                          "    <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
395                          "    <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"false\" />\n" +
396                          "  </inspection_tool>\n" +
397                          "</profile>");
398   }
399
400   public void testDisabledUnusedSymbolWithoutChanges() throws Exception {
401     checkMergedNoChanges("<profile version=\"1.0\">\n" +
402                          "  <option name=\"myName\" value=\"" +
403                          PROFILE +
404                          "\" />\n" +
405                          "  <inspection_tool class=\"UNUSED_SYMBOL\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
406                          "    <option name=\"LOCAL_VARIABLE\" value=\"true\" />\n" +
407                          "    <option name=\"FIELD\" value=\"true\" />\n" +
408                          "    <option name=\"METHOD\" value=\"true\" />\n" +
409                          "    <option name=\"CLASS\" value=\"true\" />\n" +
410                          "    <option name=\"PARAMETER\" value=\"true\" />\n" +
411                          "    <option name=\"REPORT_PARAMETER_FOR_PUBLIC_METHODS\" value=\"true\" />\n" +
412                          "  </inspection_tool>\n" +
413                          "</profile>");
414   }
415
416   public void testEnabledUnusedSymbolWithChanges() throws Exception {
417     checkMergedNoChanges("<profile version=\"1.0\">\n" +
418                          "  <option name=\"myName\" value=\"" +
419                          PROFILE +
420                          "\" />\n" +
421                          "  <inspection_tool class=\"UNUSED_SYMBOL\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n" +
422                          "    <option name=\"LOCAL_VARIABLE\" value=\"true\" />\n" +
423                          "    <option name=\"FIELD\" value=\"true\" />\n" +
424                          "    <option name=\"METHOD\" value=\"true\" />\n" +
425                          "    <option name=\"CLASS\" value=\"true\" />\n" +
426                          "    <option name=\"PARAMETER\" value=\"true\" />\n" +
427                          "    <option name=\"REPORT_PARAMETER_FOR_PUBLIC_METHODS\" value=\"false\" />\n" +
428                          "  </inspection_tool>\n" +
429                          "</profile>");
430   }
431
432   private static void checkMergedNoChanges(String initialText) throws Exception {
433     final Element element = JDOMUtil.loadDocument(initialText).getRootElement();
434     InspectionProfileImpl profile = createProfile(new InspectionProfileImpl("foo"));
435     profile.readExternal(element);
436     ModifiableModel model = profile.getModifiableModel();
437     model.commit();
438     assertEquals(initialText, serialize(profile));
439   }
440
441   public void testLockProfile() throws Exception {
442     final List<InspectionToolWrapper> list = new ArrayList<>();
443     list.add(createTool("foo", true));
444
445     InspectionToolRegistrar registrar = new InspectionToolRegistrar() {
446       @NotNull
447       @Override
448       public List<InspectionToolWrapper> createTools() {
449         return list;
450       }
451     };
452
453     InspectionProfileImpl profile = createProfile(registrar);
454
455     List<ScopeToolState> tools = profile.getAllTools(getProject());
456     assertEquals(1, tools.size());
457     assertTrue(profile.isToolEnabled(HighlightDisplayKey.find("foo")));
458     assertTrue(profile.getToolDefaultState("foo", getProject()).isEnabled());
459
460     InspectionProfileImpl model = profile.getModifiableModel();
461     model.lockProfile(true);
462     model.initInspectionTools(getProject()); // todo commit should take care of initialization
463     model.commit();
464
465     assertEquals("<profile version=\"1.0\" is_locked=\"true\">\n" +
466                  "  <option name=\"myName\" value=\"Foo\" />\n" +
467                  "  <inspection_tool class=\"foo\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\" />\n" +
468                  "</profile>",
469                  serialize(profile));
470
471     Element element = serializeProfile(profile);
472
473     list.add(createTool("bar", true));
474     list.add(createTool("disabled", false));
475
476     profile = createProfile(registrar);
477     profile.readExternal(element);
478
479     tools = profile.getAllTools(getProject());
480     assertEquals(3, tools.size());
481
482     assertTrue(profile.isProfileLocked());
483     assertFalse(profile.isToolEnabled(HighlightDisplayKey.find("bar")));
484     assertFalse(profile.isToolEnabled(HighlightDisplayKey.find("disabled")));
485
486     assertTrue(profile.getToolDefaultState("bar", getProject()).isEnabled());
487     assertFalse(profile.getToolDefaultState("disabled", getProject()).isEnabled());
488
489     assertEquals("<profile version=\"1.0\" is_locked=\"true\">\n" +
490                  "  <option name=\"myName\" value=\"Foo\" />\n" +
491                  "  <inspection_tool class=\"bar\" enabled=\"false\" level=\"ERROR\" enabled_by_default=\"true\" />\n" +
492                  "  <inspection_tool class=\"disabled\" enabled=\"false\" level=\"ERROR\" enabled_by_default=\"false\" />\n" +
493                  "  <inspection_tool class=\"foo\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"true\" />\n" +
494                  "</profile>", serialize(profile));
495   }
496
497   private static String serialize(InspectionProfileImpl profile) throws WriteExternalException {
498     return JDOMUtil.writeElement(serializeProfile(profile));
499   }
500
501   private static InspectionProfileImpl createProfile(@NotNull InspectionToolRegistrar registrar) {
502     InspectionProfileImpl base = new InspectionProfileImpl("Base", registrar, InspectionProfileManager.getInstance(), null, null);
503     return new InspectionProfileImpl("Foo", registrar, InspectionProfileManager.getInstance(), base, null);
504   }
505
506   public void testGlobalInspectionContext() throws Exception {
507     InspectionProfileImpl profile = new InspectionProfileImpl("Foo");
508     profile.disableAllTools(getProject());
509     profile.enableTool(new UnusedDeclarationInspectionBase(true).getShortName(), getProject());
510
511     GlobalInspectionContextImpl context = ((InspectionManagerEx)InspectionManager.getInstance(getProject())).createNewGlobalContext(false);
512     context.setExternalProfile(profile);
513     context.initializeTools(new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
514   }
515
516   public void testInspectionsInitialization() throws Exception {
517
518     InspectionProfileImpl foo = new InspectionProfileImpl("foo");
519     assertEquals(0, countInitializedTools(foo));
520     foo.initInspectionTools(getProject());
521     assertEquals(0, countInitializedTools(foo));
522
523     ModifiableModel model = foo.getModifiableModel();
524     assertEquals(0, countInitializedTools(model));
525     model.commit();
526     assertEquals(0, countInitializedTools(model));
527     assertEquals(0, countInitializedTools(foo));
528
529     model = foo.getModifiableModel();
530     assertEquals(0, countInitializedTools(model));
531     List<ScopeToolState> tools = ((InspectionProfileImpl)model).getAllTools(getProject());
532     for (ScopeToolState tool : tools) {
533       if (!tool.isEnabled()) {
534         tool.setEnabled(true);
535       }
536     }
537     model.commit();
538     assertEquals(0, countInitializedTools(model));
539   }
540
541   public void testDoNotInstantiateOnSave() throws Exception {
542     InspectionProfileImpl profile = new InspectionProfileImpl("profile", InspectionToolRegistrar.getInstance(), InspectionProfileManager.getInstance(), InspectionProfileImpl.getDefaultProfile(), null);
543     assertEquals(0, countInitializedTools(profile));
544     InspectionToolWrapper[] toolWrappers = profile.getInspectionTools(null);
545     assertTrue(toolWrappers.length > 0);
546     InspectionToolWrapper toolWrapper = profile.getInspectionTool(new DataFlowInspection().getShortName(), getProject());
547     assertNotNull(toolWrapper);
548     String id = toolWrapper.getShortName();
549     System.out.println(id);
550     if (profile.isToolEnabled(HighlightDisplayKey.findById(id))) {
551       profile.disableTool(id, getProject());
552     }
553     else {
554       profile.enableTool(id, getProject());
555     }
556     assertEquals(0, countInitializedTools(profile));
557     serializeProfile(profile);
558     List<InspectionToolWrapper> initializedTools = getInitializedTools(profile);
559     if (initializedTools.size() > 0) {
560       for (InspectionToolWrapper initializedTool : initializedTools) {
561         System.out.println(initializedTool.getShortName());
562       }
563       fail();
564     }
565   }
566
567   public void testInspectionInitializationForSerialization() throws Exception {
568     InspectionProfileImpl foo = new InspectionProfileImpl("foo");
569     foo.readExternal(JDOMUtil.loadDocument("<profile version=\"1.0\">\n" +
570                                            "    <option name=\"myName\" value=\"idea.default\" />\n" +
571                                            "    <inspection_tool class=\"AbstractMethodCallInConstructor\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n" +
572                                            "    <inspection_tool class=\"AssignmentToForLoopParameter\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n" +
573                                            "      <option name=\"m_checkForeachParameters\" value=\"false\" />\n" +
574                                            "    </inspection_tool>\n" +
575                                            "</profile>").getRootElement());
576     foo.initInspectionTools(getProject());
577     assertEquals(1, countInitializedTools(foo));
578   }
579
580   public void testPreserveCompatibility() throws Exception {
581     InspectionProfileImpl foo = new InspectionProfileImpl("foo", InspectionToolRegistrar.getInstance(), InspectionProjectProfileManager.getInstance(getProject()));
582     String test = "<profile version=\"1.0\" is_locked=\"false\">\n" +
583                  "  <option name=\"myName\" value=\"idea.default\" />\n" +
584                  "  <option name=\"myLocal\" value=\"false\" />\n" +
585                  "  <inspection_tool class=\"AbstractMethodCallInConstructor\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\" />\n" +
586                  "  <inspection_tool class=\"AssignmentToForLoopParameter\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n" +
587                  "    <option name=\"m_checkForeachParameters\" value=\"false\" />\n" +
588                  "  </inspection_tool>\n" +
589                  "</profile>";
590     foo.readExternal(JDOMUtil.loadDocument(test).getRootElement());
591     foo.initInspectionTools(getProject());
592     assertEquals(test, JDOMUtil.writeElement(serializeProfile(foo)));
593   }
594
595   public static int countInitializedTools(@NotNull Profile foo) {
596     return getInitializedTools((InspectionProfileImpl)foo).size();
597   }
598
599   @NotNull
600   public static List<InspectionToolWrapper> getInitializedTools(@NotNull InspectionProfileImpl foo) {
601     List<InspectionToolWrapper> initialized = null;
602     List<ScopeToolState> tools = foo.getAllTools(getProject());
603     for (ScopeToolState tool : tools) {
604       InspectionToolWrapper toolWrapper = tool.getTool();
605       if (toolWrapper.isInitialized()) {
606         if (initialized == null) {
607           initialized = new SmartList<>();
608         }
609         initialized.add(toolWrapper);
610       }
611     }
612     return initialized == null ? Collections.emptyList() : initialized;
613   }
614
615   private static LocalInspectionToolWrapper createTool(String s, boolean enabled) {
616     LocalInspectionEP foo = new LocalInspectionEP();
617     foo.shortName = s;
618     foo.displayName = s;
619     foo.groupDisplayName = s;
620     foo.level = "ERROR";
621     foo.enabledByDefault = enabled;
622     foo.implementationClass = TestTool.class.getName();
623     return new LocalInspectionToolWrapper(foo);
624   }
625
626   @SuppressWarnings("InspectionDescriptionNotFoundInspection")
627   public static class TestTool extends LocalInspectionTool {
628
629   }
630 }