blob: c1223d719167d9bf088ce356d895a0bb853efc51 [file] [log] [blame]
/*
* 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;
}
}