blob: 346a4446090af3109cdecc565305785364a92714 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection.ex;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.InspectionProfileConvertor;
import com.intellij.codeInspection.InspectionEP;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.ModifiableModel;
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.ExternalInfo;
import com.intellij.openapi.options.ExternalizableScheme;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.profile.DefaultProjectProfileManager;
import com.intellij.profile.ProfileEx;
import com.intellij.profile.ProfileManager;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.SeverityProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.graph.CachingSemiGraph;
import com.intellij.util.graph.DFSTBuilder;
import com.intellij.util.graph.GraphGenerator;
import gnu.trove.THashMap;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.io.IOException;
import java.util.*;
/**
* @author max
*/
public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, InspectionProfile, ExternalizableScheme {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.InspectionProfileImpl");
@NonNls private static final String VALID_VERSION = "1.0";
private Map<String, ToolsImpl> myTools = new THashMap<String, ToolsImpl>();
private Map<String, Boolean> myDisplayLevelMap;
@NotNull
private final Map<String, Element> myDeinstalledInspectionsSettings;
private boolean myLockedProfile = false;
protected InspectionProfileImpl mySource;
private InspectionProfileImpl myBaseProfile = null;
@NonNls private static final String VERSION_TAG = "version";
@NonNls private static final String INSPECTION_TOOL_TAG = "inspection_tool";
@NonNls private static final String CLASS_TAG = "class";
@NonNls private static final String PROFILE_NAME_TAG = "profile_name";
@NonNls private static final String ROOT_ELEMENT_TAG = "inspections";
private String myEnabledTool = null;
@NonNls private static final String USED_LEVELS = "used_levels";
final InspectionToolRegistrar myRegistrar;
@NonNls private static final String IS_LOCKED = "is_locked";
private final ExternalInfo myExternalInfo = new ExternalInfo();
@TestOnly
public static boolean INIT_INSPECTIONS = false;
private String[] myScopesOrder = null;
@Override
public void setModified(final boolean modified) {
myModified = modified;
}
private boolean myModified = false;
private volatile boolean myInitialized;
InspectionProfileImpl(@NotNull InspectionProfileImpl inspectionProfile) {
super(inspectionProfile.getName());
myRegistrar = inspectionProfile.myRegistrar;
myDeinstalledInspectionsSettings = new LinkedHashMap<String, Element>(inspectionProfile.myDeinstalledInspectionsSettings);
myBaseProfile = inspectionProfile.myBaseProfile;
myLocal = inspectionProfile.myLocal;
myLockedProfile = inspectionProfile.myLockedProfile;
mySource = inspectionProfile;
setProfileManager(inspectionProfile.getProfileManager());
copyFrom(inspectionProfile);
}
public InspectionProfileImpl(@NotNull final String profileName,
@NotNull InspectionToolRegistrar registrar,
@NotNull final ProfileManager profileManager) {
super(profileName);
myRegistrar = registrar;
myBaseProfile = getDefaultProfile();
setProfileManager(profileManager);
myDeinstalledInspectionsSettings = new TreeMap<String, Element>();
}
public InspectionProfileImpl(@NotNull @NonNls String profileName) {
super(profileName);
myRegistrar = InspectionToolRegistrar.getInstance();
setProfileManager(InspectionProfileManager.getInstance());
myDeinstalledInspectionsSettings = new TreeMap<String, Element>();
}
@NotNull
public static InspectionProfileImpl createSimple(@NotNull String name,
@NotNull Project project,
@NotNull final InspectionToolWrapper... toolWrappers) {
InspectionToolRegistrar registrar = new InspectionToolRegistrar() {
@NotNull
@Override
public List<InspectionToolWrapper> createTools() {
return Arrays.asList(toolWrappers);
}
};
InspectionProfileImpl profile = new InspectionProfileImpl(name, registrar, InspectionProfileManager.getInstance());
boolean init = INIT_INSPECTIONS;
try {
INIT_INSPECTIONS = true;
profile.initialize(project);
}
finally {
INIT_INSPECTIONS = init;
}
for (InspectionToolWrapper toolWrapper : toolWrappers) {
profile.enableTool(toolWrapper.getShortName(), project);
}
return profile;
}
@Override
public InspectionProfile getParentProfile() {
return mySource;
}
@Override
public String getBaseProfileName() {
if (myBaseProfile == null) return null;
return myBaseProfile.getName();
}
@Override
public void setBaseProfile(InspectionProfile profile) {
myBaseProfile = (InspectionProfileImpl)profile;
}
@Override
@SuppressWarnings({"SimplifiableIfStatement"})
public boolean isChanged() {
if (mySource != null && mySource.myLockedProfile != myLockedProfile) return true;
return myModified;
}
private static boolean toolSettingsAreEqual(@NotNull String toolName, @NotNull InspectionProfileImpl profile1, @NotNull InspectionProfileImpl profile2) {
final Tools toolList1 = profile1.myTools.get(toolName);
final Tools toolList2 = profile2.myTools.get(toolName);
return Comparing.equal(toolList1, toolList2);
}
@Override
public boolean isProperSetting(@NotNull String toolId) {
if (myBaseProfile != null) {
final Tools tools = myBaseProfile.getTools(toolId, null);
final Tools currentTools = myTools.get(toolId);
return !Comparing.equal(tools, currentTools);
}
return false;
}
@Override
public void resetToBase(Project project) {
initInspectionTools(project);
copyToolsConfigurations(myBaseProfile, project);
myDisplayLevelMap = null;
}
@Override
public void resetToEmpty(Project project) {
initInspectionTools(project);
final InspectionToolWrapper[] profileEntries = getInspectionTools(null);
for (InspectionToolWrapper toolWrapper : profileEntries) {
disableTool(toolWrapper.getShortName(), project);
}
}
@Override
public HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey inspectionToolKey, PsiElement element) {
Project project = element == null ? null : element.getProject();
final ToolsImpl tools = getTools(inspectionToolKey.toString(), project);
HighlightDisplayLevel level = tools != null ? tools.getLevel(element) : HighlightDisplayLevel.WARNING;
if (!((SeverityProvider)getProfileManager()).getOwnSeverityRegistrar().isSeverityValid(level.getSeverity().getName())) {
level = HighlightDisplayLevel.WARNING;
setErrorLevel(inspectionToolKey, level, project);
}
return level;
}
@Override
public void readExternal(@NotNull Element element) throws InvalidDataException {
super.readExternal(element);
final String locked = element.getAttributeValue(IS_LOCKED);
if (locked != null) {
myLockedProfile = Boolean.parseBoolean(locked);
}
if (!ApplicationManager.getApplication().isUnitTestMode() || myBaseProfile == null) {
// todo remove this strange side effect
myBaseProfile = getDefaultProfile();
}
final String version = element.getAttributeValue(VERSION_TAG);
if (version == null || !version.equals(VALID_VERSION)) {
try {
element = InspectionProfileConvertor.convertToNewFormat(element, this);
}
catch (IOException e) {
LOG.error(e);
}
catch (JDOMException e) {
LOG.error(e);
}
}
final Element highlightElement = element.getChild(USED_LEVELS);
if (highlightElement != null) { //from old profiles
((SeverityProvider)getProfileManager()).getOwnSeverityRegistrar().readExternal(highlightElement);
}
for (final Object o : element.getChildren(INSPECTION_TOOL_TAG)) {
// make clone to avoid retaining memory via o.parent pointers
Element toolElement = ((Element)o).clone();
IdeaPluginDescriptorImpl.internJDOMElement(toolElement);
String toolClassName = toolElement.getAttributeValue(CLASS_TAG);
myDeinstalledInspectionsSettings.put(toolClassName, toolElement);
}
}
@NotNull
public Set<HighlightSeverity> getUsedSeverities() {
LOG.assertTrue(myInitialized);
final Set<HighlightSeverity> result = new HashSet<HighlightSeverity>();
for (Tools tools : myTools.values()) {
for (ScopeToolState state : tools.getTools()) {
result.add(state.getLevel().getSeverity());
}
}
return result;
}
@Override
public void writeExternal(@NotNull Element element) throws WriteExternalException {
super.writeExternal(element);
element.setAttribute(VERSION_TAG, VALID_VERSION);
element.setAttribute(IS_LOCKED, String.valueOf(myLockedProfile));
synchronized (myExternalInfo) {
if (!myInitialized) {
for (Element el : myDeinstalledInspectionsSettings.values()) {
element.addContent(el.clone());
}
return;
}
}
Map<String, Boolean> diffMap = getDisplayLevelMap();
if (diffMap != null) {
diffMap = new TreeMap<String, Boolean>(diffMap);
for (String toolName : myDeinstalledInspectionsSettings.keySet()) {
diffMap.put(toolName, false);
}
for (final String toolName : diffMap.keySet()) {
if (!myLockedProfile && diffMap.get(toolName).booleanValue()) continue;
final Element toolElement = myDeinstalledInspectionsSettings.get(toolName);
if (toolElement == null) {
final ToolsImpl toolList = myTools.get(toolName);
LOG.assertTrue(toolList != null);
final Element inspectionElement = new Element(INSPECTION_TOOL_TAG);
inspectionElement.setAttribute(CLASS_TAG, toolName);
toolList.writeExternal(inspectionElement);
element.addContent(inspectionElement);
}
else {
element.addContent(toolElement.clone());
}
}
}
}
public void collectDependentInspections(@NotNull InspectionToolWrapper toolWrapper,
@NotNull Set<InspectionToolWrapper> dependentEntries,
Project project) {
String mainToolId = toolWrapper.getMainToolId();
if (mainToolId != null) {
InspectionToolWrapper dependentEntryWrapper = getInspectionTool(mainToolId, project);
if (dependentEntryWrapper != null) {
if (!dependentEntries.add(dependentEntryWrapper)) {
collectDependentInspections(dependentEntryWrapper, dependentEntries, project);
}
}
else {
LOG.error("Can't find main tool: " + mainToolId);
}
}
}
@Override
@Nullable
public InspectionToolWrapper getInspectionTool(@NotNull String shortName, @NotNull PsiElement element) {
final Tools toolList = getTools(shortName, element.getProject());
return toolList == null ? null : toolList.getInspectionTool(element);
}
@Nullable
@Override
public InspectionProfileEntry getUnwrappedTool(@NotNull String shortName, @NotNull PsiElement element) {
InspectionToolWrapper tool = getInspectionTool(shortName, element);
return tool == null ? null : tool.getTool();
}
@Override
public <T extends InspectionProfileEntry> T getUnwrappedTool(@NotNull Key<T> shortNameKey, @NotNull PsiElement element) {
//noinspection unchecked
return (T) getUnwrappedTool(shortNameKey.toString(), element);
}
@Override
public void modifyProfile(@NotNull Consumer<ModifiableModel> modelConsumer) {
ModifiableModel model = getModifiableModel();
modelConsumer.consume(model);
try {
model.commit();
}
catch (IOException e) {
LOG.error(e);
}
}
@Override
public <T extends InspectionProfileEntry> void modifyToolSettings(@NotNull final Key<T> shortNameKey,
@NotNull final PsiElement psiElement,
@NotNull final Consumer<T> toolConsumer) {
modifyProfile(new Consumer<ModifiableModel>() {
@Override
public void consume(@NotNull ModifiableModel model) {
InspectionProfileEntry tool = model.getUnwrappedTool(shortNameKey.toString(), psiElement);
//noinspection unchecked
toolConsumer.consume((T) tool);
}
});
}
@Override
@Nullable
public InspectionToolWrapper getInspectionTool(@NotNull String shortName, Project project) {
final ToolsImpl tools = getTools(shortName, project);
return tools != null? tools.getTool() : null;
}
public InspectionToolWrapper getToolById(@NotNull String id, @NotNull PsiElement element) {
initInspectionTools(element.getProject());
for (Tools toolList : myTools.values()) {
final InspectionToolWrapper tool = toolList.getInspectionTool(element);
String toolId =
tool instanceof LocalInspectionToolWrapper ? ((LocalInspectionToolWrapper)tool).getID() : tool.getShortName();
if (id.equals(toolId)) return tool;
}
return null;
}
@Override
public void save() throws IOException {
InspectionProfileManager.getInstance().fireProfileChanged(this);
}
@Override
public boolean isEditable() {
return myEnabledTool == null;
}
@Override
@NotNull
public String getDisplayName() {
return isEditable() ? getName() : myEnabledTool;
}
@Override
public void scopesChanged() {
for (ScopeToolState toolState : getAllTools(null)) {
toolState.scopesChanged();
}
InspectionProfileManager.getInstance().fireProfileChanged(this);
}
@Override
public void setEditable(final String displayName) {
myEnabledTool = displayName;
}
@Override
public boolean isProfileLocked() {
return myLockedProfile;
}
@Override
public void lockProfile(boolean isLocked) {
myLockedProfile = isLocked;
}
@Override
@NotNull
public InspectionToolWrapper[] getInspectionTools(@Nullable PsiElement element) {
initInspectionTools(element == null ? null : element.getProject());
List<InspectionToolWrapper> result = new ArrayList<InspectionToolWrapper>();
for (Tools toolList : myTools.values()) {
result.add(toolList.getInspectionTool(element));
}
return result.toArray(new InspectionToolWrapper[result.size()]);
}
@Override
@NotNull
public List<Tools> getAllEnabledInspectionTools(Project project) {
initInspectionTools(project);
List<Tools> result = new ArrayList<Tools>();
for (final ToolsImpl toolList : myTools.values()) {
if (toolList.isEnabled()) {
result.add(toolList);
}
}
return result;
}
@Override
public void disableTool(@NotNull String toolId, @NotNull PsiElement element) {
getTools(toolId, element.getProject()).disableTool(element);
}
public void disableToolByDefault(@NotNull List<String> toolIds, Project project) {
for (final String toolId : toolIds) {
getToolDefaultState(toolId, project).setEnabled(false);
}
}
@NotNull
public ScopeToolState getToolDefaultState(@NotNull String toolId, Project project) {
return getTools(toolId, project).getDefaultState();
}
public void enableToolsByDefault(@NotNull List<String> toolIds, Project project) {
for (final String toolId : toolIds) {
getToolDefaultState(toolId, project).setEnabled(true);
}
}
public boolean wasInitialized() {
return myInitialized;
}
public void initInspectionTools(@Nullable Project project) {
if (ApplicationManager.getApplication().isUnitTestMode() && !INIT_INSPECTIONS) return;
if (myInitialized) return;
synchronized (myExternalInfo) {
if (myInitialized) return;
myInitialized = initialize(project);
}
}
private boolean initialize(@Nullable Project project) {
if (myBaseProfile != null) {
myBaseProfile.initInspectionTools(project);
}
final List<InspectionToolWrapper> tools;
try {
tools = createTools(project);
}
catch (ProcessCanceledException e) {
return false;
}
final Map<String, List<String>> dependencies = new HashMap<String, List<String>>();
for (InspectionToolWrapper toolWrapper : tools) {
final String shortName = toolWrapper.getShortName();
HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
if (key == null) {
final InspectionEP extension = toolWrapper.getExtension();
Computable<String> computable = extension == null ? new Computable.PredefinedValueComputable<String>(toolWrapper.getDisplayName()) : new Computable<String>() {
@Override
public String compute() {
return extension.getDisplayName();
}
};
if (toolWrapper instanceof LocalInspectionToolWrapper) {
key = HighlightDisplayKey.register(shortName, computable, ((LocalInspectionToolWrapper)toolWrapper).getID(),
((LocalInspectionToolWrapper)toolWrapper).getAlternativeID());
}
else {
key = HighlightDisplayKey.register(shortName, computable);
}
}
LOG.assertTrue(key != null, shortName + " ; number of initialized tools: " + myTools.size());
HighlightDisplayLevel level = myBaseProfile != null ? myBaseProfile.getErrorLevel(key, project) : toolWrapper.getDefaultLevel();
boolean enabled = myBaseProfile != null ? myBaseProfile.isToolEnabled(key) : toolWrapper.isEnabledByDefault();
final ToolsImpl toolsList = new ToolsImpl(toolWrapper, level, !myLockedProfile && enabled, enabled);
final Element element = myDeinstalledInspectionsSettings.remove(toolWrapper.getShortName());
if (element != null) {
try {
toolsList.readExternal(element, this, dependencies);
}
catch (InvalidDataException e) {
LOG.error("Can't read settings for " + toolWrapper, e);
}
}
myTools.put(toolWrapper.getShortName(), toolsList);
}
final GraphGenerator<String> graphGenerator = GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<String>() {
@Override
public Collection<String> getNodes() {
return dependencies.keySet();
}
@Override
public Iterator<String> getIn(String n) {
return dependencies.get(n).iterator();
}
}));
DFSTBuilder<String> builder = new DFSTBuilder<String>(graphGenerator);
if (builder.isAcyclic()) {
final List<String> scopes = builder.getSortedNodes();
myScopesOrder = ArrayUtil.toStringArray(scopes);
}
if (mySource != null) {
copyToolsConfigurations(mySource, project);
}
return true;
}
@Nullable
public String[] getScopesOrder() {
return myScopesOrder;
}
public void setScopesOrder(String[] scopesOrder) {
myScopesOrder = scopesOrder;
}
@NotNull
private List<InspectionToolWrapper> createTools(Project project) {
if (mySource != null) {
return ContainerUtil.map(mySource.getDefaultStates(project), new Function<ScopeToolState, InspectionToolWrapper>() {
@NotNull
@Override
public InspectionToolWrapper fun(@NotNull ScopeToolState state) {
return state.getTool();
}
});
}
return myRegistrar.createTools();
}
private HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key, Project project) {
final ToolsImpl tools = getTools(key.toString(), project);
LOG.assertTrue(tools != null, "profile name: " + myName + " base profile: " + (myBaseProfile != null ? myBaseProfile.getName() : "-") + " key: " + key);
return tools.getLevel();
}
@Override
@NotNull
public ModifiableModel getModifiableModel() {
InspectionProfileImpl modifiableModel = new InspectionProfileImpl(this);
modifiableModel.myExternalInfo.copy(myExternalInfo);
return modifiableModel;
}
@Override
public void copyFrom(@NotNull InspectionProfile profile) {
super.copyFrom(profile);
final InspectionProfileImpl inspectionProfile = (InspectionProfileImpl)profile;
myBaseProfile = inspectionProfile.myBaseProfile;
}
private void copyToolsConfigurations(@NotNull InspectionProfileImpl profile, @Nullable Project project) {
try {
for (ToolsImpl toolList : profile.myTools.values()) {
final ToolsImpl tools = myTools.get(toolList.getShortName());
final ScopeToolState defaultState = toolList.getDefaultState();
tools.setDefaultState(copyToolSettings(defaultState.getTool()), defaultState.isEnabled(), defaultState.getLevel());
tools.removeAllScopes();
final List<ScopeToolState> nonDefaultToolStates = toolList.getNonDefaultTools();
if (nonDefaultToolStates != null) {
for (ScopeToolState state : nonDefaultToolStates) {
final InspectionToolWrapper toolWrapper = copyToolSettings(state.getTool());
final NamedScope scope = state.getScope(project);
if (scope != null) {
tools.addTool(scope, toolWrapper, state.isEnabled(), state.getLevel());
}
else {
tools.addTool(state.getScopeName(), toolWrapper, state.isEnabled(), state.getLevel());
}
}
}
tools.setEnabled(toolList.isEnabled());
}
}
catch (WriteExternalException e) {
LOG.error(e);
}
catch (InvalidDataException e) {
LOG.error(e);
}
}
@NotNull
private static InspectionToolWrapper copyToolSettings(@NotNull InspectionToolWrapper toolWrapper)
throws WriteExternalException, InvalidDataException {
final InspectionToolWrapper inspectionTool = toolWrapper.createCopy();
if (toolWrapper.isInitialized()) {
@NonNls String tempRoot = "config";
Element config = new Element(tempRoot);
toolWrapper.getTool().writeSettings(config);
inspectionTool.getTool().readSettings(config);
}
return inspectionTool;
}
@Override
public void cleanup(@NotNull Project project) {
for (final ToolsImpl toolList : myTools.values()) {
if (toolList.isEnabled()) {
for (InspectionToolWrapper toolWrapper : toolList.getAllTools()) {
toolWrapper.projectClosed(project);
toolWrapper.cleanup(project);
}
}
}
}
public void enableTool(@NotNull String toolId, Project project) {
final ToolsImpl tools = getTools(toolId, project);
tools.setEnabled(true);
if (tools.getNonDefaultTools() == null) {
tools.getDefaultState().setEnabled(true);
}
}
@Override
public void enableTool(@NotNull String inspectionTool, NamedScope namedScope, Project project) {
getTools(inspectionTool, project).enableTool(namedScope, project);
}
public void enableTools(@NotNull List<String> inspectionTools, NamedScope namedScope, Project project) {
for (String inspectionTool : inspectionTools) {
enableTool(inspectionTool, namedScope, project);
}
}
@Override
public void disableTool(@NotNull String inspectionTool, NamedScope namedScope, @NotNull Project project) {
getTools(inspectionTool, project).disableTool(namedScope, project);
}
public void disableTools(@NotNull List<String> inspectionTools, NamedScope namedScope, @NotNull Project project) {
for (String inspectionTool : inspectionTools) {
disableTool(inspectionTool, namedScope, project);
}
}
@Override
public void disableTool(@NotNull String inspectionTool, Project project) {
final ToolsImpl tools = getTools(inspectionTool, project);
tools.setEnabled(false);
if (tools.getNonDefaultTools() == null) {
tools.getDefaultState().setEnabled(false);
}
}
@Override
public void setErrorLevel(@NotNull HighlightDisplayKey key, @NotNull HighlightDisplayLevel level, Project project) {
getTools(key.toString(), project).setLevel(level);
}
@Override
public boolean isToolEnabled(HighlightDisplayKey key, PsiElement element) {
if (key == null) {
return false;
}
final Tools toolState = getTools(key.toString(), element == null ? null : element.getProject());
return toolState != null && toolState.isEnabled(element);
}
@Override
public boolean isToolEnabled(HighlightDisplayKey key) {
return isToolEnabled(key, null);
}
@Override
public boolean isExecutable(Project project) {
initInspectionTools(project);
for (Tools tools : myTools.values()) {
if (tools.isEnabled()) return true;
}
return false;
}
//invoke when isChanged() == true
@Override
public void commit() throws IOException {
LOG.assertTrue(mySource != null);
mySource.commit(this);
getProfileManager().updateProfile(mySource);
mySource = null;
}
private void commit(@NotNull InspectionProfileImpl inspectionProfile) {
setName(inspectionProfile.getName());
myLocal = inspectionProfile.myLocal;
myLockedProfile = inspectionProfile.myLockedProfile;
myDisplayLevelMap = inspectionProfile.myDisplayLevelMap;
myBaseProfile = inspectionProfile.myBaseProfile;
myTools = inspectionProfile.myTools;
myProfileManager = inspectionProfile.getProfileManager();
myExternalInfo.copy(inspectionProfile.getExternalInfo());
InspectionProfileManager.getInstance().fireProfileChanged(inspectionProfile);
}
private static class InspectionProfileImplHolder {
private static final InspectionProfileImpl DEFAULT_PROFILE = new InspectionProfileImpl("Default");
}
@NotNull
public static InspectionProfileImpl getDefaultProfile() {
return InspectionProfileImplHolder.DEFAULT_PROFILE;
}
public Element saveToDocument() throws WriteExternalException {
if (isLocal()) {
Element root = new Element(ROOT_ELEMENT_TAG);
root.setAttribute(PROFILE_NAME_TAG, myName);
writeExternal(root);
//myVisibleTreeState.writeExternal(root);
return root;
}
else {
return null;
}
}
@Override
public void convert(@NotNull Element element, @NotNull Project project) {
initInspectionTools(project);
final Element scopes = element.getChild(DefaultProjectProfileManager.SCOPES);
if (scopes == null) {
return;
}
final List children = scopes.getChildren(SCOPE);
for (Object s : children) {
Element scopeElement = (Element)s;
final String profile = scopeElement.getAttributeValue(DefaultProjectProfileManager.PROFILE);
if (profile != null) {
final InspectionProfileImpl inspectionProfile = (InspectionProfileImpl)getProfileManager().getProfile(profile);
if (inspectionProfile != null) {
final NamedScope scope = getProfileManager().getScopesManager().getScope(scopeElement.getAttributeValue(NAME));
if (scope != null) {
for (InspectionToolWrapper toolWrapper : inspectionProfile.getInspectionTools(null)) {
final HighlightDisplayKey key = HighlightDisplayKey.find(toolWrapper.getShortName());
try {
InspectionToolWrapper toolWrapperCopy = copyToolSettings(toolWrapper);
HighlightDisplayLevel errorLevel = inspectionProfile.getErrorLevel(key, null, project);
getTools(toolWrapper.getShortName(), project).addTool(scope, toolWrapperCopy, inspectionProfile.isToolEnabled(key), errorLevel);
}
catch (Exception e) {
LOG.error(e);
}
}
}
}
}
}
reduceConvertedScopes();
}
private void reduceConvertedScopes() {
for (ToolsImpl tools : myTools.values()) {
final ScopeToolState toolState = tools.getDefaultState();
final List<ScopeToolState> nonDefaultTools = tools.getNonDefaultTools();
if (nonDefaultTools != null) {
boolean equal = true;
boolean isEnabled = toolState.isEnabled();
for (ScopeToolState state : nonDefaultTools) {
isEnabled |= state.isEnabled();
if (!state.equalTo(toolState)) {
equal = false;
}
}
tools.setEnabled(isEnabled);
if (equal) {
tools.removeAllScopes();
}
}
}
}
@Override
@NotNull
public ExternalInfo getExternalInfo() {
return myExternalInfo;
}
@NotNull
public List<ScopeToolState> getAllTools(Project project) {
initInspectionTools(project);
final List<ScopeToolState> result = new ArrayList<ScopeToolState>();
for (Tools tools : myTools.values()) {
result.addAll(tools.getTools());
}
return result;
}
@NotNull
public List<ScopeToolState> getDefaultStates(Project project) {
initInspectionTools(project);
final List<ScopeToolState> result = new ArrayList<ScopeToolState>();
for (Tools tools : myTools.values()) {
result.add(tools.getDefaultState());
}
return result;
}
@NotNull
public List<ScopeToolState> getNonDefaultTools(@NotNull String shortName, Project project) {
final List<ScopeToolState> result = new ArrayList<ScopeToolState>();
final List<ScopeToolState> nonDefaultTools = getTools(shortName, project).getNonDefaultTools();
if (nonDefaultTools != null) {
result.addAll(nonDefaultTools);
}
return result;
}
public boolean isToolEnabled(@NotNull HighlightDisplayKey key, NamedScope namedScope, Project project) {
return getTools(key.toString(), project).isEnabled(namedScope,project);
}
@Deprecated
public void removeScope(@NotNull String toolId, int scopeIdx, Project project) {
getTools(toolId, project).removeScope(scopeIdx);
}
public void removeScope(@NotNull String toolId, @NotNull String scopeName, Project project) {
getTools(toolId, project).removeScope(scopeName);
}
public void removeScopes(@NotNull List<String> toolIds, @NotNull String scopeName, Project project) {
for (final String toolId : toolIds) {
removeScope(toolId, scopeName, project);
}
}
public void removeAllScopes(@NotNull String toolId, Project project) {
getTools(toolId, project).removeAllScopes();
}
public void moveScope(@NotNull String toolId, int idx, int dir, Project project) {
getTools(toolId, project).moveScope(idx, dir);
}
/**
* @return null if it has no base profile
*/
@Nullable
private Map<String, Boolean> getDisplayLevelMap() {
if (myBaseProfile == null) return null;
if (myDisplayLevelMap == null) {
initInspectionTools(null);
myDisplayLevelMap = new TreeMap<String, Boolean>();
for (String toolId : myTools.keySet()) {
myDisplayLevelMap.put(toolId, toolSettingsAreEqual(toolId, myBaseProfile, this));
}
}
return myDisplayLevelMap;
}
@Override
public void profileChanged() {
myDisplayLevelMap = null;
}
@NotNull
public HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key, NamedScope scope, Project project) {
final ToolsImpl tools = getTools(key.toString(), project);
return tools != null ? tools.getLevel(scope, project) : HighlightDisplayLevel.WARNING;
}
public ScopeToolState addScope(@NotNull InspectionToolWrapper toolWrapper,
NamedScope scope,
@NotNull HighlightDisplayLevel level,
boolean enabled,
Project project) {
return getTools(toolWrapper.getShortName(), project).prependTool(scope, toolWrapper, enabled, level);
}
public void setErrorLevel(@NotNull HighlightDisplayKey key, @NotNull HighlightDisplayLevel level, String scopeName, Project project) {
getTools(key.toString(), project).setLevel(level, scopeName, project);
}
public void setErrorLevel(@NotNull List<HighlightDisplayKey> keys, @NotNull HighlightDisplayLevel level, String scopeName, Project project) {
for (HighlightDisplayKey key : keys) {
setErrorLevel(key, level, scopeName, project);
}
}
public ToolsImpl getTools(@NotNull String toolId, Project project) {
initInspectionTools(project);
return myTools.get(toolId);
}
public void enableAllTools(Project project) {
for (InspectionToolWrapper entry : getInspectionTools(null)) {
enableTool(entry.getShortName(), project);
}
}
public void disableAllTools(Project project) {
for (InspectionToolWrapper entry : getInspectionTools(null)) {
disableTool(entry.getShortName(), project);
}
}
@NotNull
public String toString() {
return mySource == null ? getName() : getName() + " (copy)";
}
@Override
public boolean equals(Object o) {
return super.equals(o) && ((InspectionProfileImpl)o).getProfileManager() == getProfileManager();
}
}