| /* |
| * Copyright 2000-2013 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.codeInspection.*; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.components.ServiceManager; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.extensions.Extensions; |
| import com.intellij.openapi.progress.ProgressManager; |
| import com.intellij.openapi.util.Factory; |
| import com.intellij.util.containers.ContainerUtil; |
| import gnu.trove.THashSet; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.TestOnly; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| /** |
| * @author max |
| */ |
| public class InspectionToolRegistrar { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.InspectionToolRegistrar"); |
| |
| private final List<Factory<InspectionToolWrapper>> myInspectionToolFactories = new ArrayList<Factory<InspectionToolWrapper>>(); |
| |
| private final AtomicBoolean myInspectionComponentsLoaded = new AtomicBoolean(false); |
| |
| public void ensureInitialized() { |
| if (!myInspectionComponentsLoaded.getAndSet(true)) { |
| Set<InspectionToolProvider> providers = new THashSet<InspectionToolProvider>(); |
| ContainerUtil.addAll(providers, ApplicationManager.getApplication().getComponents(InspectionToolProvider.class)); |
| ContainerUtil.addAll(providers, Extensions.getExtensions(InspectionToolProvider.EXTENSION_POINT_NAME)); |
| registerTools(providers.toArray(new InspectionToolProvider[providers.size()])); |
| for (final LocalInspectionEP ep : Extensions.getExtensions(LocalInspectionEP.LOCAL_INSPECTION)) { |
| myInspectionToolFactories.add(new Factory<InspectionToolWrapper>() { |
| @Override |
| public InspectionToolWrapper create() { |
| return new LocalInspectionToolWrapper(ep); |
| } |
| }); |
| } |
| for (final InspectionEP ep : Extensions.getExtensions(InspectionEP.GLOBAL_INSPECTION)) { |
| myInspectionToolFactories.add(new Factory<InspectionToolWrapper>() { |
| @Override |
| public InspectionToolWrapper create() { |
| return new GlobalInspectionToolWrapper(ep); |
| } |
| }); |
| } |
| for (InspectionToolsFactory factory : Extensions.getExtensions(InspectionToolsFactory.EXTENSION_POINT_NAME)) { |
| for (final InspectionProfileEntry profileEntry : factory.createTools()) { |
| myInspectionToolFactories.add(new Factory<InspectionToolWrapper>() { |
| @Override |
| public InspectionToolWrapper create() { |
| return wrapTool(profileEntry); |
| } |
| }); |
| } |
| } |
| } |
| } |
| |
| @NotNull |
| public static InspectionToolWrapper wrapTool(@NotNull InspectionProfileEntry profileEntry) { |
| if (profileEntry instanceof LocalInspectionTool) { |
| return new LocalInspectionToolWrapper((LocalInspectionTool)profileEntry); |
| } |
| if (profileEntry instanceof GlobalInspectionTool) { |
| return new GlobalInspectionToolWrapper((GlobalInspectionTool)profileEntry); |
| } |
| throw new RuntimeException("unknown inspection class: " + profileEntry + "; "+profileEntry.getClass()); |
| } |
| |
| public void registerTools(@NotNull InspectionToolProvider[] providers) { |
| for (InspectionToolProvider provider : providers) { |
| Class[] classes = provider.getInspectionClasses(); |
| for (Class aClass : classes) { |
| registerInspectionTool(aClass); |
| } |
| } |
| } |
| |
| @NotNull |
| private Factory<InspectionToolWrapper> registerInspectionTool(@NotNull final Class aClass) { |
| if (LocalInspectionTool.class.isAssignableFrom(aClass)) { |
| return registerLocalInspection(aClass, true); |
| } |
| if (GlobalInspectionTool.class.isAssignableFrom(aClass)) { |
| return registerGlobalInspection(aClass, true); |
| } |
| throw new RuntimeException("unknown inspection class: " + aClass); |
| } |
| |
| public static InspectionToolRegistrar getInstance() { |
| return ServiceManager.getService(InspectionToolRegistrar.class); |
| } |
| |
| /** |
| * make sure that it is not too late |
| */ |
| @NotNull |
| public Factory<InspectionToolWrapper> registerInspectionToolFactory(@NotNull Factory<InspectionToolWrapper> factory, boolean store) { |
| if (store) { |
| myInspectionToolFactories.add(factory); |
| } |
| return factory; |
| } |
| |
| @NotNull |
| private Factory<InspectionToolWrapper> registerLocalInspection(final Class toolClass, boolean store) { |
| return registerInspectionToolFactory(new Factory<InspectionToolWrapper>() { |
| @Override |
| public InspectionToolWrapper create() { |
| return new LocalInspectionToolWrapper((LocalInspectionTool)InspectionToolsRegistrarCore.instantiateTool(toolClass)); |
| } |
| }, store); |
| } |
| |
| @NotNull |
| private Factory<InspectionToolWrapper> registerGlobalInspection(@NotNull final Class aClass, boolean store) { |
| return registerInspectionToolFactory(new Factory<InspectionToolWrapper>() { |
| @Override |
| public InspectionToolWrapper create() { |
| return new GlobalInspectionToolWrapper((GlobalInspectionTool) InspectionToolsRegistrarCore.instantiateTool(aClass)); |
| } |
| }, store); |
| } |
| |
| @NotNull |
| @TestOnly |
| public List<InspectionToolWrapper> createTools() { |
| ensureInitialized(); |
| |
| final List<InspectionToolWrapper> tools = ContainerUtil.newArrayListWithCapacity(myInspectionToolFactories.size()); |
| final Set<Factory<InspectionToolWrapper>> broken = ContainerUtil.newHashSet(); |
| for (final Factory<InspectionToolWrapper> factory : myInspectionToolFactories) { |
| ProgressManager.checkCanceled(); |
| final InspectionToolWrapper toolWrapper = factory.create(); |
| if (toolWrapper != null && checkTool(toolWrapper) == null) { |
| tools.add(toolWrapper); |
| } |
| else { |
| broken.add(factory); |
| } |
| } |
| myInspectionToolFactories.removeAll(broken); |
| |
| return tools; |
| } |
| |
| private static String checkTool(@NotNull final InspectionToolWrapper toolWrapper) { |
| if (!(toolWrapper instanceof LocalInspectionToolWrapper)) { |
| return null; |
| } |
| String message = null; |
| try { |
| final String id = ((LocalInspectionToolWrapper)toolWrapper).getID(); |
| if (id == null || !LocalInspectionTool.isValidID(id)) { |
| message = InspectionsBundle.message("inspection.disabled.wrong.id", toolWrapper.getShortName(), id, LocalInspectionTool.VALID_ID_PATTERN); |
| } |
| } |
| catch (Throwable t) { |
| message = InspectionsBundle.message("inspection.disabled.error", toolWrapper.getShortName(), t.getMessage()); |
| } |
| if (message != null) { |
| LOG.error(message); |
| } |
| return message; |
| } |
| } |