2 * Copyright 2000-2016 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.codeInspection.ex;
18 import com.intellij.codeHighlighting.HighlightDisplayLevel;
19 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
20 import com.intellij.codeInsight.daemon.InspectionProfileConvertor;
21 import com.intellij.codeInspection.InspectionEP;
22 import com.intellij.codeInspection.InspectionProfile;
23 import com.intellij.codeInspection.InspectionProfileEntry;
24 import com.intellij.codeInspection.ModifiableModel;
25 import com.intellij.configurationStore.SchemeDataHolder;
26 import com.intellij.configurationStore.SerializableScheme;
27 import com.intellij.lang.annotation.HighlightSeverity;
28 import com.intellij.openapi.application.ApplicationManager;
29 import com.intellij.openapi.diagnostic.Logger;
30 import com.intellij.openapi.extensions.Extensions;
31 import com.intellij.openapi.options.ExternalizableScheme;
32 import com.intellij.openapi.progress.ProcessCanceledException;
33 import com.intellij.openapi.project.Project;
34 import com.intellij.openapi.util.*;
35 import com.intellij.profile.ProfileEx;
36 import com.intellij.profile.ProfileManager;
37 import com.intellij.profile.codeInspection.InspectionProfileManager;
38 import com.intellij.profile.codeInspection.ProjectInspectionProfileManagerKt;
39 import com.intellij.profile.codeInspection.SeverityProvider;
40 import com.intellij.psi.PsiElement;
41 import com.intellij.psi.search.scope.packageSet.NamedScope;
42 import com.intellij.util.ArrayUtil;
43 import com.intellij.util.Consumer;
44 import com.intellij.util.containers.ContainerUtil;
45 import com.intellij.util.graph.CachingSemiGraph;
46 import com.intellij.util.graph.DFSTBuilder;
47 import com.intellij.util.graph.GraphGenerator;
48 import com.intellij.util.xmlb.annotations.Attribute;
49 import com.intellij.util.xmlb.annotations.Tag;
50 import com.intellij.util.xmlb.annotations.Transient;
51 import gnu.trove.THashMap;
52 import gnu.trove.THashSet;
53 import org.jdom.Element;
54 import org.jetbrains.annotations.NonNls;
55 import org.jetbrains.annotations.NotNull;
56 import org.jetbrains.annotations.Nullable;
57 import org.jetbrains.annotations.TestOnly;
64 public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, InspectionProfile, ExternalizableScheme,
66 @NonNls static final String INSPECTION_TOOL_TAG = "inspection_tool";
67 @NonNls static final String CLASS_TAG = "class";
68 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.InspectionProfileImpl");
69 @NonNls private static final String VALID_VERSION = "1.0";
70 @NonNls private static final String VERSION_TAG = "version";
71 @NonNls private static final String USED_LEVELS = "used_levels";
72 public static final String DEFAULT_PROFILE_NAME = "Default";
74 public static boolean INIT_INSPECTIONS = false;
75 private final InspectionToolRegistrar myRegistrar;
77 private final Map<String, Element> myInspectionsSettings = new TreeMap<>();
78 protected InspectionProfileImpl mySource;
79 private Map<String, ToolsImpl> myTools = new THashMap<>();
80 private volatile Map<String, Boolean> myDisplayLevelMap;
81 @Attribute("is_locked")
82 private boolean myLockedProfile;
83 private final InspectionProfileImpl myBaseProfile;
84 private volatile String myToolShortName = null;
85 private String[] myScopesOrder;
86 private String myDescription;
87 private boolean myModified;
88 private volatile boolean myInitialized;
90 private final Object myLock = new Object();
92 private SchemeDataHolder<InspectionProfileImpl> myDataHolder;
94 InspectionProfileImpl(@NotNull InspectionProfileImpl inspectionProfile) {
95 this(inspectionProfile.getName(), inspectionProfile.myRegistrar, inspectionProfile.getProfileManager(), inspectionProfile.myBaseProfile, null);
96 myInspectionsSettings.putAll(inspectionProfile.myInspectionsSettings);
98 setProjectLevel(inspectionProfile.isProjectLevel());
99 myLockedProfile = inspectionProfile.myLockedProfile;
100 mySource = inspectionProfile;
101 copyFrom(inspectionProfile);
104 public InspectionProfileImpl(@NotNull String profileName,
105 @NotNull InspectionToolRegistrar registrar,
106 @NotNull ProfileManager profileManager) {
107 this(profileName, registrar, profileManager, getDefaultProfile(), null);
110 public InspectionProfileImpl(@NotNull @NonNls String profileName) {
111 this(profileName, InspectionToolRegistrar.getInstance(), InspectionProfileManager.getInstance(), null, null);
114 public InspectionProfileImpl(@NotNull String profileName,
115 @NotNull InspectionToolRegistrar registrar,
116 @NotNull ProfileManager profileManager,
117 @Nullable InspectionProfileImpl baseProfile,
118 @Nullable SchemeDataHolder<InspectionProfileImpl> dataHolder) {
121 myRegistrar = registrar;
122 myBaseProfile = baseProfile;
123 myDataHolder = dataHolder;
124 myProfileManager = profileManager;
128 public static InspectionProfileImpl createSimple(@NotNull String name,
129 @NotNull Project project,
130 @NotNull List<InspectionToolWrapper> toolWrappers) {
131 InspectionProfileImpl profile = new InspectionProfileImpl(name, new InspectionToolRegistrar() {
134 public List<InspectionToolWrapper> createTools() {
137 }, InspectionProfileManager.getInstance());
138 for (InspectionToolWrapper toolWrapper : toolWrappers) {
139 profile.enableTool(toolWrapper.getShortName(), project);
144 private static boolean toolSettingsAreEqual(@NotNull String toolName, @NotNull InspectionProfileImpl profile1, @NotNull InspectionProfileImpl profile2) {
145 final Tools toolList1 = profile1.myTools.get(toolName);
146 final Tools toolList2 = profile2.myTools.get(toolName);
148 return Comparing.equal(toolList1, toolList2);
152 private static InspectionToolWrapper copyToolSettings(@NotNull InspectionToolWrapper toolWrapper)
153 throws WriteExternalException, InvalidDataException {
154 final InspectionToolWrapper inspectionTool = toolWrapper.createCopy();
155 if (toolWrapper.isInitialized()) {
156 @NonNls String tempRoot = "config";
157 Element config = new Element(tempRoot);
158 toolWrapper.getTool().writeSettings(config);
159 inspectionTool.getTool().readSettings(config);
161 return inspectionTool;
165 public static InspectionProfileImpl getDefaultProfile() {
166 return InspectionProfileImplHolder.DEFAULT_PROFILE;
170 public void setModified(final boolean modified) {
171 myModified = modified;
175 public InspectionProfile getParentProfile() {
180 @SuppressWarnings({"SimplifiableIfStatement"})
181 public boolean isChanged() {
182 if (mySource != null && mySource.myLockedProfile != myLockedProfile) return true;
187 public boolean isProperSetting(@NotNull String toolId) {
188 if (myBaseProfile != null) {
189 final Tools tools = myBaseProfile.getTools(toolId, null);
190 final Tools currentTools = myTools.get(toolId);
191 return !Comparing.equal(tools, currentTools);
197 public void resetToBase(Project project) {
198 initInspectionTools(project);
200 copyToolsConfigurations(myBaseProfile, project);
201 myDisplayLevelMap = null;
205 public void resetToEmpty(Project project) {
206 initInspectionTools(project);
207 final InspectionToolWrapper[] profileEntries = getInspectionTools(null);
208 for (InspectionToolWrapper toolWrapper : profileEntries) {
209 disableTool(toolWrapper.getShortName(), project);
214 public HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey inspectionToolKey, PsiElement element) {
215 Project project = element == null ? null : element.getProject();
216 final ToolsImpl tools = getTools(inspectionToolKey.toString(), project);
217 HighlightDisplayLevel level = tools != null ? tools.getLevel(element) : HighlightDisplayLevel.WARNING;
218 if (!((SeverityProvider)getProfileManager()).getOwnSeverityRegistrar().isSeverityValid(level.getSeverity().getName())) {
219 level = HighlightDisplayLevel.WARNING;
220 setErrorLevel(inspectionToolKey, level, project);
226 public void readExternal(@NotNull Element element) {
227 super.readExternal(element);
229 final String version = element.getAttributeValue(VERSION_TAG);
230 if (version == null || !version.equals(VALID_VERSION)) {
231 element = InspectionProfileConvertor.convertToNewFormat(element, this);
234 final Element highlightElement = element.getChild(USED_LEVELS);
235 if (highlightElement != null) {
237 ((SeverityProvider)getProfileManager()).getOwnSeverityRegistrar().readExternal(highlightElement);
240 for (Element toolElement : element.getChildren(INSPECTION_TOOL_TAG)) {
241 myInspectionsSettings.put(toolElement.getAttributeValue(CLASS_TAG), toolElement.clone());
246 public Set<HighlightSeverity> getUsedSeverities() {
247 LOG.assertTrue(myInitialized);
248 Set<HighlightSeverity> result = new THashSet<>();
249 for (Tools tools : myTools.values()) {
250 for (ScopeToolState state : tools.getTools()) {
251 result.add(state.getLevel().getSeverity());
258 public Element writeScheme() {
259 if (myDataHolder != null) {
260 return myDataHolder.read();
263 Element result = isProjectLevel() ? new Element("profile").setAttribute("version", "1.0") : new Element("inspections").setAttribute("profile_name", getName());
264 serializeInto(result, false);
266 if (isProjectLevel()) {
267 return new Element("component").setAttribute("name", "InspectionProjectProfileManager").addContent(result);
273 public void serializeInto(@NotNull Element element, boolean preserveCompatibility) {
274 // must be first - compatibility
275 element.setAttribute(VERSION_TAG, VALID_VERSION);
277 super.serializeInto(element, preserveCompatibility);
279 synchronized (myLock) {
280 if (!myInitialized) {
281 for (Element el : myInspectionsSettings.values()) {
282 element.addContent(el.clone());
288 Map<String, Boolean> diffMap = getDisplayLevelMap();
289 if (diffMap == null) {
293 diffMap = new TreeMap<>(diffMap);
294 for (String toolName : myInspectionsSettings.keySet()) {
295 diffMap.put(toolName, false);
298 for (String toolName : diffMap.keySet()) {
299 if (!myLockedProfile && diffMap.get(toolName).booleanValue()) {
300 markSettingsMerged(toolName, element);
304 Element toolElement = myInspectionsSettings.get(toolName);
305 if (toolElement == null) {
306 ToolsImpl toolList = myTools.get(toolName);
307 LOG.assertTrue(toolList != null);
308 Element inspectionElement = new Element(INSPECTION_TOOL_TAG);
309 inspectionElement.setAttribute(CLASS_TAG, toolName);
311 toolList.writeExternal(inspectionElement);
313 catch (WriteExternalException e) {
318 if (!areSettingsMerged(toolName, inspectionElement)) {
319 element.addContent(inspectionElement);
323 element.addContent(toolElement.clone());
328 private void markSettingsMerged(@NotNull String toolName, @NotNull Element element) {
329 //add marker if already merged but result is now default (-> empty node)
330 final String mergedName = InspectionElementsMergerBase.getMergedMarkerName(toolName);
331 if (!myUninstalledInspectionsSettings.containsKey(mergedName)) {
332 final InspectionElementsMergerBase merger = getMerger(toolName);
333 if (merger != null && merger.markSettingsMerged(myUninstalledInspectionsSettings)) {
334 element.addContent(new Element(INSPECTION_TOOL_TAG).setAttribute(CLASS_TAG, mergedName));
339 private boolean areSettingsMerged(String toolName, Element inspectionElement) {
340 //skip merged settings as they could be restored from already provided data
341 final InspectionElementsMergerBase merger = getMerger(toolName);
342 return merger != null && merger.areSettingsMerged(myUninstalledInspectionsSettings, inspectionElement);
345 public void collectDependentInspections(@NotNull InspectionToolWrapper toolWrapper,
346 @NotNull Set<InspectionToolWrapper> dependentEntries,
348 String mainToolId = toolWrapper.getMainToolId();
350 if (mainToolId != null) {
351 InspectionToolWrapper dependentEntryWrapper = getInspectionTool(mainToolId, project);
353 if (dependentEntryWrapper == null) {
354 LOG.error("Can't find main tool: '" + mainToolId+"' which was specified in "+toolWrapper);
357 if (!dependentEntries.add(dependentEntryWrapper)) {
358 collectDependentInspections(dependentEntryWrapper, dependentEntries, project);
365 public InspectionToolWrapper getInspectionTool(@NotNull String shortName, @NotNull PsiElement element) {
366 final Tools toolList = getTools(shortName, element.getProject());
367 return toolList == null ? null : toolList.getInspectionTool(element);
372 public InspectionProfileEntry getUnwrappedTool(@NotNull String shortName, @NotNull PsiElement element) {
373 InspectionToolWrapper tool = getInspectionTool(shortName, element);
374 return tool == null ? null : tool.getTool();
378 public <T extends InspectionProfileEntry> T getUnwrappedTool(@NotNull Key<T> shortNameKey, @NotNull PsiElement element) {
379 //noinspection unchecked
380 return (T) getUnwrappedTool(shortNameKey.toString(), element);
384 public void modifyProfile(@NotNull Consumer<ModifiableModel> modelConsumer) {
385 ModifiableModel model = getModifiableModel();
386 modelConsumer.consume(model);
391 public <T extends InspectionProfileEntry> void modifyToolSettings(@NotNull final Key<T> shortNameKey,
392 @NotNull final PsiElement psiElement,
393 @NotNull final Consumer<T> toolConsumer) {
394 modifyProfile(model -> {
395 InspectionProfileEntry tool = model.getUnwrappedTool(shortNameKey.toString(), psiElement);
396 //noinspection unchecked
397 toolConsumer.consume((T) tool);
403 public InspectionToolWrapper getInspectionTool(@NotNull String shortName, Project project) {
404 final ToolsImpl tools = getTools(shortName, project);
405 return tools != null? tools.getTool() : null;
408 public InspectionToolWrapper getToolById(@NotNull String id, @NotNull PsiElement element) {
409 initInspectionTools(element.getProject());
410 for (Tools toolList : myTools.values()) {
411 final InspectionToolWrapper tool = toolList.getInspectionTool(element);
412 if (id.equals(tool.getID())) return tool;
418 public List<InspectionToolWrapper> findToolsById(@NotNull String id, @NotNull PsiElement element) {
419 List<InspectionToolWrapper> result = null;
420 initInspectionTools(element.getProject());
421 for (Tools toolList : myTools.values()) {
422 final InspectionToolWrapper tool = toolList.getInspectionTool(element);
423 if (id.equals(tool.getID())) {
424 if (result == null) {
425 result = new ArrayList<>();
435 InspectionProfileManager.getInstance().fireProfileChanged(this);
440 public String getSingleTool() {
441 return myToolShortName;
445 public void setSingleTool(@NotNull final String toolShortName) {
446 myToolShortName = toolShortName;
451 public String getDisplayName() {
456 public void scopesChanged() {
457 for (ScopeToolState toolState : getAllTools(null)) {
458 toolState.scopesChanged();
460 InspectionProfileManager.getInstance().fireProfileChanged(this);
465 public boolean isProfileLocked() {
466 return myLockedProfile;
470 public void lockProfile(boolean isLocked) {
471 myLockedProfile = isLocked;
476 public InspectionToolWrapper[] getInspectionTools(@Nullable PsiElement element) {
477 initInspectionTools(element == null ? null : element.getProject());
478 List<InspectionToolWrapper> result = new ArrayList<>();
479 for (Tools toolList : myTools.values()) {
480 result.add(toolList.getInspectionTool(element));
482 return result.toArray(new InspectionToolWrapper[result.size()]);
487 public List<Tools> getAllEnabledInspectionTools(Project project) {
488 initInspectionTools(project);
489 List<Tools> result = new ArrayList<>();
490 for (final ToolsImpl toolList : myTools.values()) {
491 if (toolList.isEnabled()) {
492 result.add(toolList);
499 public void disableTool(@NotNull String toolId, @NotNull PsiElement element) {
500 getTools(toolId, element.getProject()).disableTool(element);
503 public void disableToolByDefault(@NotNull Collection<String> toolIds, @Nullable Project project) {
504 for (String toolId : toolIds) {
505 getToolDefaultState(toolId, project).setEnabled(false);
510 public ScopeToolState getToolDefaultState(@NotNull String toolId, @Nullable Project project) {
511 return getTools(toolId, project).getDefaultState();
514 public void enableToolsByDefault(@NotNull List<String> toolIds, Project project) {
515 for (final String toolId : toolIds) {
516 getToolDefaultState(toolId, project).setEnabled(true);
520 public boolean wasInitialized() {
521 return myInitialized;
524 public void initInspectionTools(@Nullable Project project) {
525 //noinspection TestOnlyProblems
526 if (myInitialized || (ApplicationManager.getApplication().isUnitTestMode() && !INIT_INSPECTIONS)) {
530 synchronized (myLock) {
531 if (!myInitialized) {
537 private void initialize(@Nullable Project project) {
538 SchemeDataHolder<InspectionProfileImpl> dataHolder = myDataHolder;
539 if (dataHolder != null) {
541 Element element = dataHolder.read();
542 if (element.getName().equals("component")) {
543 element = element.getChild("profile");
545 assert element != null;
546 readExternal(element);
549 if (myBaseProfile != null) {
550 myBaseProfile.initInspectionTools(project);
553 final List<InspectionToolWrapper> tools;
555 tools = createTools(project);
557 catch (ProcessCanceledException ignored) {
561 final Map<String, List<String>> dependencies = new THashMap<>();
562 for (InspectionToolWrapper toolWrapper : tools) {
563 addTool(project, toolWrapper, dependencies);
566 DFSTBuilder<String> builder = new DFSTBuilder<>(GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<String>() {
568 public Collection<String> getNodes() {
569 return dependencies.keySet();
573 public Iterator<String> getIn(String n) {
574 return dependencies.get(n).iterator();
577 if (builder.isAcyclic()) {
578 myScopesOrder = ArrayUtil.toStringArray(builder.getSortedNodes());
581 if (mySource != null) {
582 copyToolsConfigurations(mySource, project);
585 myInitialized = true;
586 if (dataHolder != null) {
587 // should be only after set myInitialized
588 dataHolder.updateDigest(this);
592 public void addTool(@Nullable Project project, @NotNull InspectionToolWrapper toolWrapper, @NotNull Map<String, List<String>> dependencies) {
593 final String shortName = toolWrapper.getShortName();
594 HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
596 final InspectionEP extension = toolWrapper.getExtension();
597 Computable<String> computable = extension == null ? new Computable.PredefinedValueComputable<>(toolWrapper.getDisplayName()) : extension::getDisplayName;
598 if (toolWrapper instanceof LocalInspectionToolWrapper) {
599 key = HighlightDisplayKey.register(shortName, computable, toolWrapper.getID(),
600 ((LocalInspectionToolWrapper)toolWrapper).getAlternativeID());
603 key = HighlightDisplayKey.register(shortName, computable);
608 LOG.error(shortName + " ; number of initialized tools: " + myTools.size());
612 HighlightDisplayLevel baseLevel = myBaseProfile != null && myBaseProfile.getTools(shortName, project) != null
613 ? myBaseProfile.getErrorLevel(key, project)
614 : HighlightDisplayLevel.DO_NOT_SHOW;
615 HighlightDisplayLevel defaultLevel = toolWrapper.getDefaultLevel();
616 HighlightDisplayLevel level = baseLevel.getSeverity().compareTo(defaultLevel.getSeverity()) > 0 ? baseLevel : defaultLevel;
617 //HighlightDisplayLevel level = myBaseProfile != null && myBaseProfile.getTools(shortName, project) != null ? myBaseProfile.getErrorLevel(key, project) : toolWrapper.getDefaultLevel();
618 boolean enabled = myBaseProfile != null ? myBaseProfile.isToolEnabled(key) : toolWrapper.isEnabledByDefault();
619 final ToolsImpl toolsList = new ToolsImpl(toolWrapper, level, !myLockedProfile && enabled, enabled);
620 final Element element = myInspectionsSettings.remove(shortName);
622 if (element != null) {
623 toolsList.readExternal(element, this, dependencies);
625 else if (!myUninstalledInspectionsSettings.containsKey(InspectionElementsMergerBase.getMergedMarkerName(shortName))) {
626 final InspectionElementsMergerBase merger = getMerger(shortName);
627 if (merger != null) {
628 final Element merged = merger.merge(myInspectionsSettings);
629 if (merged != null) {
630 toolsList.readExternal(merged, this, dependencies);
635 catch (InvalidDataException e) {
636 LOG.error("Can't read settings for " + toolWrapper, e);
638 myTools.put(shortName, toolsList);
642 private static InspectionElementsMergerBase getMerger(String shortName) {
643 final InspectionElementsMerger merger = InspectionElementsMerger.getMerger(shortName);
644 if (merger instanceof InspectionElementsMergerBase) {
645 return (InspectionElementsMergerBase)merger;
647 return merger != null ? new InspectionElementsMergerBase() {
649 public String getMergedToolName() {
650 return merger.getMergedToolName();
654 public String[] getSourceToolNames() {
655 return merger.getSourceToolNames();
662 public String[] getScopesOrder() {
663 return myScopesOrder;
666 public void setScopesOrder(String[] scopesOrder) {
667 myScopesOrder = scopesOrder;
671 private List<InspectionToolWrapper> createTools(@Nullable Project project) {
672 if (mySource != null) {
673 return ContainerUtil.map(mySource.getDefaultStates(project), ScopeToolState::getTool);
675 return myRegistrar.createTools();
678 private HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key, @Nullable Project project) {
679 final ToolsImpl tools = getTools(key.toString(), project);
680 LOG.assertTrue(tools != null, "profile name: " + myName + " base profile: " + (myBaseProfile != null ? myBaseProfile.getName() : "-") + " key: " + key);
681 return tools.getLevel();
686 public InspectionProfileImpl getModifiableModel() {
687 return new InspectionProfileImpl(this);
690 private void copyToolsConfigurations(@NotNull InspectionProfileImpl profile, @Nullable Project project) {
692 for (ToolsImpl toolList : profile.myTools.values()) {
693 final ToolsImpl tools = myTools.get(toolList.getShortName());
694 final ScopeToolState defaultState = toolList.getDefaultState();
695 tools.setDefaultState(copyToolSettings(defaultState.getTool()), defaultState.isEnabled(), defaultState.getLevel());
696 tools.removeAllScopes();
697 final List<ScopeToolState> nonDefaultToolStates = toolList.getNonDefaultTools();
698 if (nonDefaultToolStates != null) {
699 for (ScopeToolState state : nonDefaultToolStates) {
700 final InspectionToolWrapper toolWrapper = copyToolSettings(state.getTool());
701 final NamedScope scope = state.getScope(project);
703 tools.addTool(scope, toolWrapper, state.isEnabled(), state.getLevel());
706 tools.addTool(state.getScopeName(), toolWrapper, state.isEnabled(), state.getLevel());
710 tools.setEnabled(toolList.isEnabled());
713 catch (WriteExternalException e) {
716 catch (InvalidDataException e) {
722 public void cleanup(@NotNull Project project) {
723 if (!myInitialized) {
727 for (final ToolsImpl toolList : myTools.values()) {
728 if (toolList.isEnabled()) {
729 for (InspectionToolWrapper toolWrapper : toolList.getAllTools()) {
730 toolWrapper.cleanup(project);
736 public void enableTool(@NotNull String toolId, Project project) {
737 final ToolsImpl tools = getTools(toolId, project);
738 tools.setEnabled(true);
739 if (tools.getNonDefaultTools() == null) {
740 tools.getDefaultState().setEnabled(true);
745 public void enableTool(@NotNull String inspectionTool, NamedScope namedScope, Project project) {
746 getTools(inspectionTool, project).enableTool(namedScope, project);
749 public void enableTools(@NotNull List<String> inspectionTools, NamedScope namedScope, Project project) {
750 for (String inspectionTool : inspectionTools) {
751 enableTool(inspectionTool, namedScope, project);
756 public void disableTool(@NotNull String inspectionTool, NamedScope namedScope, @NotNull Project project) {
757 getTools(inspectionTool, project).disableTool(namedScope, project);
760 public void disableTools(@NotNull List<String> inspectionTools, NamedScope namedScope, @NotNull Project project) {
761 for (String inspectionTool : inspectionTools) {
762 disableTool(inspectionTool, namedScope, project);
767 public void disableTool(@NotNull String inspectionTool, Project project) {
768 final ToolsImpl tools = getTools(inspectionTool, project);
769 tools.setEnabled(false);
770 if (tools.getNonDefaultTools() == null) {
771 tools.getDefaultState().setEnabled(false);
776 public void setErrorLevel(@NotNull HighlightDisplayKey key, @NotNull HighlightDisplayLevel level, Project project) {
777 getTools(key.toString(), project).setLevel(level);
781 public boolean isToolEnabled(@Nullable HighlightDisplayKey key, PsiElement element) {
785 final Tools toolState = getTools(key.toString(), element == null ? null : element.getProject());
786 return toolState != null && toolState.isEnabled(element);
790 public boolean isToolEnabled(@Nullable HighlightDisplayKey key) {
791 return isToolEnabled(key, null);
795 public boolean isExecutable(Project project) {
796 initInspectionTools(project);
797 for (Tools tools : myTools.values()) {
798 if (tools.isEnabled()) return true;
803 //invoke when isChanged() == true
805 public void commit() {
806 LOG.assertTrue(mySource != null);
807 mySource.commit(this);
808 getProfileManager().updateProfile(mySource);
812 private void commit(@NotNull InspectionProfileImpl model) {
813 setName(model.getName());
814 setDescription(model.getDescription());
815 setProjectLevel(model.isProjectLevel());
816 myLockedProfile = model.myLockedProfile;
817 myDisplayLevelMap = model.myDisplayLevelMap;
818 myTools = model.myTools;
819 myProfileManager = model.getProfileManager();
821 InspectionProfileManager.getInstance().fireProfileChanged(model);
825 public String getDescription() {
826 return myDescription;
829 public void setDescription(String description) {
830 myDescription = description;
833 public void convert(@NotNull Element element, @NotNull Project project) {
834 final Element scopes = element.getChild("scopes");
835 if (scopes == null) {
839 initInspectionTools(project);
841 for (Element scopeElement : scopes.getChildren(SCOPE)) {
842 final String profile = scopeElement.getAttributeValue(ProjectInspectionProfileManagerKt.PROFILE);
843 if (profile != null) {
844 final InspectionProfileImpl inspectionProfile = (InspectionProfileImpl)getProfileManager().getProfile(profile);
845 if (inspectionProfile != null) {
846 final NamedScope scope = getProfileManager().getScopesManager().getScope(scopeElement.getAttributeValue(NAME));
848 for (InspectionToolWrapper toolWrapper : inspectionProfile.getInspectionTools(null)) {
849 final HighlightDisplayKey key = HighlightDisplayKey.find(toolWrapper.getShortName());
851 InspectionToolWrapper toolWrapperCopy = copyToolSettings(toolWrapper);
852 HighlightDisplayLevel errorLevel = inspectionProfile.getErrorLevel(key, null, project);
853 getTools(toolWrapper.getShortName(), project).addTool(scope, toolWrapperCopy, inspectionProfile.isToolEnabled(key), errorLevel);
855 catch (Exception e) {
863 reduceConvertedScopes();
866 private void reduceConvertedScopes() {
867 for (ToolsImpl tools : myTools.values()) {
868 final ScopeToolState toolState = tools.getDefaultState();
869 final List<ScopeToolState> nonDefaultTools = tools.getNonDefaultTools();
870 if (nonDefaultTools != null) {
871 boolean equal = true;
872 boolean isEnabled = toolState.isEnabled();
873 for (ScopeToolState state : nonDefaultTools) {
874 isEnabled |= state.isEnabled();
875 if (!state.equalTo(toolState)) {
879 tools.setEnabled(isEnabled);
881 tools.removeAllScopes();
888 public List<ScopeToolState> getAllTools(@Nullable Project project) {
889 initInspectionTools(project);
891 List<ScopeToolState> result = new ArrayList<>();
892 for (Tools tools : myTools.values()) {
893 tools.collectTools(result);
899 public List<ScopeToolState> getDefaultStates(@Nullable Project project) {
900 initInspectionTools(project);
901 final List<ScopeToolState> result = new ArrayList<>();
902 for (Tools tools : myTools.values()) {
903 result.add(tools.getDefaultState());
909 public List<ScopeToolState> getNonDefaultTools(@NotNull String shortName, Project project) {
910 final List<ScopeToolState> result = new ArrayList<>();
911 final List<ScopeToolState> nonDefaultTools = getTools(shortName, project).getNonDefaultTools();
912 if (nonDefaultTools != null) {
913 result.addAll(nonDefaultTools);
918 public boolean isToolEnabled(@NotNull HighlightDisplayKey key, NamedScope namedScope, Project project) {
919 return getTools(key.toString(), project).isEnabled(namedScope,project);
922 public void removeScope(@NotNull String toolId, @NotNull String scopeName, Project project) {
923 getTools(toolId, project).removeScope(scopeName);
926 public void removeScopes(@NotNull List<String> toolIds, @NotNull String scopeName, Project project) {
927 for (final String toolId : toolIds) {
928 removeScope(toolId, scopeName, project);
933 * @return null if it has no base profile
936 private Map<String, Boolean> getDisplayLevelMap() {
937 if (myBaseProfile == null) return null;
938 if (myDisplayLevelMap == null) {
939 synchronized (myLock) {
940 if (myDisplayLevelMap == null) {
941 initInspectionTools(null);
942 Set<String> names = myTools.keySet();
943 Map<String, Boolean> map = new THashMap<>(names.size());
944 for (String toolId : names) {
945 map.put(toolId, toolSettingsAreEqual(toolId, myBaseProfile, this));
947 myDisplayLevelMap = map;
952 return myDisplayLevelMap;
955 public void profileChanged() {
956 myDisplayLevelMap = null;
961 public HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key, NamedScope scope, Project project) {
962 final ToolsImpl tools = getTools(key.toString(), project);
963 return tools != null ? tools.getLevel(scope, project) : HighlightDisplayLevel.WARNING;
966 public ScopeToolState addScope(@NotNull InspectionToolWrapper toolWrapper,
968 @NotNull HighlightDisplayLevel level,
971 return getTools(toolWrapper.getShortName(), project).prependTool(scope, toolWrapper, enabled, level);
974 public void setErrorLevel(@NotNull HighlightDisplayKey key, @NotNull HighlightDisplayLevel level, String scopeName, Project project) {
975 getTools(key.toString(), project).setLevel(level, scopeName, project);
978 public void setErrorLevel(@NotNull List<HighlightDisplayKey> keys, @NotNull HighlightDisplayLevel level, String scopeName, Project project) {
979 for (HighlightDisplayKey key : keys) {
980 setErrorLevel(key, level, scopeName, project);
984 public ToolsImpl getTools(@NotNull String toolId, @Nullable Project project) {
985 initInspectionTools(project);
986 return myTools.get(toolId);
989 public void enableAllTools(Project project) {
990 for (InspectionToolWrapper entry : getInspectionTools(null)) {
991 enableTool(entry.getShortName(), project);
995 public void disableAllTools(Project project) {
996 for (InspectionToolWrapper entry : getInspectionTools(null)) {
997 disableTool(entry.getShortName(), project);
1003 public String toString() {
1004 return mySource == null ? getName() : getName() + " (copy)";
1008 public boolean equals(Object o) {
1009 return super.equals(o) && ((InspectionProfileImpl)o).getProfileManager() == getProfileManager();
1012 private static class InspectionProfileImplHolder {
1013 private static final InspectionProfileImpl DEFAULT_PROFILE = new InspectionProfileImpl(DEFAULT_PROFILE_NAME);