/* * Copyright 2000-2015 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.profile.codeInspection; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeInsight.daemon.InspectionProfileConvertor; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.SeveritiesProvider; import com.intellij.codeInsight.daemon.impl.SeverityRegistrar; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.codeInspection.ex.InspectionToolRegistrar; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.options.BaseSchemeProcessor; import com.intellij.openapi.options.SchemesManager; import com.intellij.openapi.options.SchemesManagerFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.profile.Profile; import com.intellij.util.ArrayUtil; import com.intellij.util.messages.MessageBus; import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.concurrent.atomic.AtomicBoolean; @State( name = "InspectionProfileManager", storages = { @Storage(file = StoragePathMacros.APP_CONFIG + "/editor.xml"), @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml", deprecated = true) }, additionalExportFile = InspectionProfileManager.FILE_SPEC ) public class InspectionProfileManagerImpl extends InspectionProfileManager implements SeverityProvider, PersistentStateComponent<Element> { private final InspectionToolRegistrar myRegistrar; private final SchemesManager<Profile, InspectionProfileImpl> mySchemesManager; private final AtomicBoolean myProfilesAreInitialized = new AtomicBoolean(false); private final SeverityRegistrar mySeverityRegistrar; protected static final Logger LOG = Logger.getInstance("#com.intellij.profile.DefaultProfileManager"); public static InspectionProfileManagerImpl getInstanceImpl() { return (InspectionProfileManagerImpl)ServiceManager.getService(InspectionProfileManager.class); } public InspectionProfileManagerImpl(@NotNull InspectionToolRegistrar registrar, @NotNull SchemesManagerFactory schemesManagerFactory, @NotNull MessageBus messageBus) { myRegistrar = registrar; registerProvidedSeverities(); mySchemesManager = schemesManagerFactory.createSchemesManager(FILE_SPEC, new BaseSchemeProcessor<InspectionProfileImpl>() { @NotNull @Override public InspectionProfileImpl readScheme(@NotNull Element element) { final InspectionProfileImpl profile = new InspectionProfileImpl(InspectionProfileLoadUtil.getProfileName(element), myRegistrar, InspectionProfileManagerImpl.this); try { profile.readExternal(element); } catch (Exception ignored) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { Messages.showErrorDialog(InspectionsBundle.message("inspection.error.loading.message", 0, profile.getName()), InspectionsBundle.message("inspection.errors.occurred.dialog.title")); } }, ModalityState.NON_MODAL); } return profile; } @NotNull @Override public State getState(@NotNull InspectionProfileImpl scheme) { return scheme.isProjectLevel() ? State.NON_PERSISTENT : (scheme.wasInitialized() ? State.POSSIBLY_CHANGED : State.UNCHANGED); } @Override public Element writeScheme(@NotNull InspectionProfileImpl scheme) { Element root = new Element("inspections"); root.setAttribute("profile_name", scheme.getName()); scheme.serializeInto(root, false); return root; } @Override public void onSchemeAdded(@NotNull final InspectionProfileImpl scheme) { updateProfileImpl(scheme); fireProfileChanged(scheme); } @Override public void onSchemeDeleted(@NotNull final InspectionProfileImpl scheme) { } @Override public void onCurrentSchemeChanged(final InspectionProfileImpl oldCurrentScheme) { Profile current = mySchemesManager.getCurrentScheme(); if (current != null) { fireProfileChanged((Profile)oldCurrentScheme, current, null); } } }, RoamingType.PER_USER); mySeverityRegistrar = new SeverityRegistrar(messageBus); } @NotNull private static InspectionProfileImpl createSampleProfile() { return new InspectionProfileImpl("Default"); } public static void registerProvidedSeverities() { for (SeveritiesProvider provider : Extensions.getExtensions(SeveritiesProvider.EP_NAME)) { for (HighlightInfoType t : provider.getSeveritiesHighlightInfoTypes()) { HighlightSeverity highlightSeverity = t.getSeverity(null); SeverityRegistrar.registerStandard(t, highlightSeverity); TextAttributesKey attributesKey = t.getAttributesKey(); Icon icon = t instanceof HighlightInfoType.Iconable ? ((HighlightInfoType.Iconable)t).getIcon() : null; HighlightDisplayLevel.registerSeverity(highlightSeverity, attributesKey, icon); } } } @Override @NotNull public Collection<Profile> getProfiles() { initProfiles(); return mySchemesManager.getAllSchemes(); } private volatile boolean LOAD_PROFILES = !ApplicationManager.getApplication().isUnitTestMode(); @TestOnly public void forceInitProfiles(boolean flag) { LOAD_PROFILES = flag; myProfilesAreInitialized.set(false); } @Override public void initProfiles() { if (myProfilesAreInitialized.getAndSet(true)) { if (mySchemesManager.getAllSchemes().isEmpty()) { createDefaultProfile(); } return; } if (!LOAD_PROFILES) return; mySchemesManager.loadSchemes(); Collection<Profile> profiles = mySchemesManager.getAllSchemes(); if (profiles.isEmpty()) { createDefaultProfile(); } else { for (Profile profile : profiles) { addProfile(profile); } } } private void createDefaultProfile() { final InspectionProfileImpl defaultProfile = (InspectionProfileImpl)createProfile(); defaultProfile.setBaseProfile(InspectionProfileImpl.getDefaultProfile()); addProfile(defaultProfile); } @Override public Profile loadProfile(@NotNull String path) throws IOException, JDOMException { final File file = new File(path); if (file.exists()) { try { return InspectionProfileLoadUtil.load(file, myRegistrar, this); } catch (IOException e) { throw e; } catch (JDOMException e) { throw e; } catch (Exception ignored) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { Messages.showErrorDialog(InspectionsBundle.message("inspection.error.loading.message", 0, file), InspectionsBundle.message("inspection.errors.occurred.dialog.title")); } }, ModalityState.NON_MODAL); } } return getProfile(path, false); } @Override public void updateProfile(@NotNull Profile profile) { mySchemesManager.addNewScheme(profile, true); updateProfileImpl(profile); } private static void updateProfileImpl(@NotNull Profile profile) { for (Project project : ProjectManager.getInstance().getOpenProjects()) { InspectionProjectProfileManager.getInstance(project).initProfileWrapper(profile); } } @NotNull @Override public SeverityRegistrar getSeverityRegistrar() { return mySeverityRegistrar; } @NotNull @Override public SeverityRegistrar getOwnSeverityRegistrar() { return mySeverityRegistrar; } @Nullable @Override public Element getState() { Element state = new Element("state"); try { mySeverityRegistrar.writeExternal(state); } catch (WriteExternalException e) { throw new RuntimeException(e); } return state; } @Override public void loadState(Element state) { try { mySeverityRegistrar.readExternal(state); } catch (InvalidDataException e) { throw new RuntimeException(e); } } public InspectionProfileConvertor getConverter() { return new InspectionProfileConvertor(this); } @Override public Profile createProfile() { return createSampleProfile(); } @Override public void setRootProfile(String rootProfile) { Profile current = mySchemesManager.getCurrentScheme(); if (current != null && !Comparing.strEqual(rootProfile, current.getName())) { fireProfileChanged(current, getProfile(rootProfile), null); } mySchemesManager.setCurrentSchemeName(rootProfile); } @Override public Profile getProfile(@NotNull final String name, boolean returnRootProfileIfNamedIsAbsent) { Profile found = mySchemesManager.findSchemeByName(name); if (found != null) return found; //profile was deleted if (returnRootProfileIfNamedIsAbsent) { return getRootProfile(); } return null; } @NotNull @Override public Profile getRootProfile() { Profile current = mySchemesManager.getCurrentScheme(); if (current != null) return current; Collection<Profile> profiles = getProfiles(); if (profiles.isEmpty()) return createSampleProfile(); return profiles.iterator().next(); } @Override public void deleteProfile(@NotNull final String profile) { Profile found = mySchemesManager.findSchemeByName(profile); if (found != null) { mySchemesManager.removeScheme(found); } } @Override public void addProfile(@NotNull final Profile profile) { mySchemesManager.addNewScheme(profile, true); } @Override @NotNull public String[] getAvailableProfileNames() { return ArrayUtil.toStringArray(mySchemesManager.getAllSchemeNames()); } @Override public Profile getProfile(@NotNull final String name) { return getProfile(name, true); } }