EA-65402 - CME: InspectionToolRegistrar.createTools
[idea/community.git] / platform / analysis-impl / src / com / intellij / codeInspection / ex / InspectionToolRegistrar.java
1 /*
2  * Copyright 2000-2015 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
17 package com.intellij.codeInspection.ex;
18
19 import com.intellij.codeInspection.*;
20 import com.intellij.openapi.application.ApplicationManager;
21 import com.intellij.openapi.components.ServiceManager;
22 import com.intellij.openapi.diagnostic.Logger;
23 import com.intellij.openapi.extensions.Extensions;
24 import com.intellij.openapi.progress.ProgressManager;
25 import com.intellij.openapi.util.Factory;
26 import com.intellij.util.containers.ContainerUtil;
27 import gnu.trove.THashSet;
28 import org.jetbrains.annotations.NotNull;
29
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.List;
33 import java.util.Set;
34
35 /**
36  * @author max
37  */
38 public class InspectionToolRegistrar {
39   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.InspectionToolRegistrar");
40
41   private final List<Factory<InspectionToolWrapper>> myInspectionToolFactories = ContainerUtil.createLockFreeCopyOnWriteList();
42
43   private boolean myInspectionComponentsLoaded = false;
44
45   private synchronized void ensureInitialized() {
46     if (!myInspectionComponentsLoaded) {
47       myInspectionComponentsLoaded = true;
48       Set<InspectionToolProvider> providers = new THashSet<InspectionToolProvider>();
49       ContainerUtil.addAll(providers, ApplicationManager.getApplication().getComponents(InspectionToolProvider.class));
50       ContainerUtil.addAll(providers, Extensions.getExtensions(InspectionToolProvider.EXTENSION_POINT_NAME));
51       List<Factory<InspectionToolWrapper>> factories = new ArrayList<Factory<InspectionToolWrapper>>();
52       registerTools(providers, factories);
53       for (final LocalInspectionEP ep : Extensions.getExtensions(LocalInspectionEP.LOCAL_INSPECTION)) {
54         factories.add(new Factory<InspectionToolWrapper>() {
55           @Override
56           public InspectionToolWrapper create() {
57             return new LocalInspectionToolWrapper(ep);
58           }
59         });
60       }
61       for (final InspectionEP ep : Extensions.getExtensions(InspectionEP.GLOBAL_INSPECTION)) {
62         factories.add(new Factory<InspectionToolWrapper>() {
63           @Override
64           public InspectionToolWrapper create() {
65             return new GlobalInspectionToolWrapper(ep);
66           }
67         });
68       }
69       for (InspectionToolsFactory factory : Extensions.getExtensions(InspectionToolsFactory.EXTENSION_POINT_NAME)) {
70         for (final InspectionProfileEntry profileEntry : factory.createTools()) {
71           factories.add(new Factory<InspectionToolWrapper>() {
72             @Override
73             public InspectionToolWrapper create() {
74               return wrapTool(profileEntry);
75             }
76           });
77         }
78       }
79       myInspectionToolFactories.addAll(factories);
80     }
81   }
82
83   @NotNull
84   public static InspectionToolWrapper wrapTool(@NotNull InspectionProfileEntry profileEntry) {
85     if (profileEntry instanceof LocalInspectionTool) {
86       return new LocalInspectionToolWrapper((LocalInspectionTool)profileEntry);
87     }
88     if (profileEntry instanceof GlobalInspectionTool) {
89       return new GlobalInspectionToolWrapper((GlobalInspectionTool)profileEntry);
90     }
91     throw new RuntimeException("unknown inspection class: " + profileEntry + "; "+profileEntry.getClass());
92   }
93
94   private static void registerTools(@NotNull Collection<InspectionToolProvider> providers,
95                                     @NotNull List<Factory<InspectionToolWrapper>> factories) {
96     for (InspectionToolProvider provider : providers) {
97       Class[] classes = provider.getInspectionClasses();
98       for (final Class aClass : classes) {
99         Factory<InspectionToolWrapper> factory = new Factory<InspectionToolWrapper>() {
100           @Override
101           public InspectionToolWrapper create() {
102             return wrapTool((InspectionProfileEntry)InspectionToolsRegistrarCore.instantiateTool(aClass));
103           }
104         };
105         factories.add(factory);
106       }
107     }
108   }
109
110   public static InspectionToolRegistrar getInstance() {
111     return ServiceManager.getService(InspectionToolRegistrar.class);
112   }
113
114   @NotNull
115   public List<InspectionToolWrapper> createTools() {
116     ensureInitialized();
117
118     final List<InspectionToolWrapper> tools = new ArrayList<InspectionToolWrapper>(myInspectionToolFactories.size());
119     for (final Factory<InspectionToolWrapper> factory : myInspectionToolFactories) {
120       ProgressManager.checkCanceled();
121       final InspectionToolWrapper toolWrapper = factory.create();
122       if (toolWrapper != null && checkTool(toolWrapper) == null) {
123         tools.add(toolWrapper);
124       }
125     }
126
127     return tools;
128   }
129
130   private static String checkTool(@NotNull final InspectionToolWrapper toolWrapper) {
131     if (!(toolWrapper instanceof LocalInspectionToolWrapper)) {
132       return null;
133     }
134     String message = null;
135     try {
136       final String id = ((LocalInspectionToolWrapper)toolWrapper).getID();
137       if (id == null || !LocalInspectionTool.isValidID(id)) {
138         message = InspectionsBundle.message("inspection.disabled.wrong.id", toolWrapper.getShortName(), id, LocalInspectionTool.VALID_ID_PATTERN);
139       }
140     }
141     catch (Throwable t) {
142       message = InspectionsBundle.message("inspection.disabled.error", toolWrapper.getShortName(), t.getMessage());
143     }
144     if (message != null) {
145       LOG.error(message);
146     }
147     return message;
148   }
149 }