blob: 2e5457b29b930d7b7335259701f7d10b840f72b0 [file] [log] [blame]
/*
* Copyright 2016 The Bazel Authors. All rights reserved.
*
* 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.google.idea.testing;
import com.intellij.lang.LanguageExtensionPoint;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.impl.ComponentManagerImpl;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import org.picocontainer.MutablePicoContainer;
/** Utility class for registering project services, application services and extensions. */
public class ServiceHelper {
public static <T> void registerExtension(
ExtensionPointName<T> name, T instance, Disposable parentDisposable) {
ExtensionPoint<T> ep = Extensions.getRootArea().getExtensionPoint(name);
ep.registerExtension(instance);
Disposer.register(parentDisposable, () -> ep.unregisterExtension(instance));
}
/** Unregister all extensions of the given class, for the given extension point. */
public static <T> void unregisterLanguageExtensionPoint(
String extensionPointKey, Class<T> clazz, Disposable parentDisposable) {
ExtensionPoint<LanguageExtensionPoint<T>> ep =
Extensions.getRootArea().getExtensionPoint(extensionPointKey);
LanguageExtensionPoint<T>[] existingExtensions = ep.getExtensions();
for (LanguageExtensionPoint<T> ext : existingExtensions) {
if (clazz.getName().equals(ext.implementationClass)) {
ep.unregisterExtension(ext);
Disposer.register(parentDisposable, () -> ep.registerExtension(ext));
}
}
}
public static <T> void registerApplicationService(
Class<T> key, T implementation, Disposable parentDisposable) {
registerComponentInstance(
(MutablePicoContainer) ApplicationManager.getApplication().getPicoContainer(),
key,
implementation,
parentDisposable);
}
public static <T> void registerApplicationComponent(
Class<T> key, T implementation, Disposable parentDisposable) {
Application application = ApplicationManager.getApplication();
if (application instanceof ComponentManagerImpl) {
replaceComponentInstance(
(ComponentManagerImpl) application, key, implementation, parentDisposable);
} else {
registerComponentInstance(
(MutablePicoContainer) application.getPicoContainer(),
key,
implementation,
parentDisposable);
}
}
public static <T> void registerProjectService(
Project project, Class<T> key, T implementation, Disposable parentDisposable) {
registerComponentInstance(
(MutablePicoContainer) project.getPicoContainer(), key, implementation, parentDisposable);
}
private static <T> void registerComponentInstance(
MutablePicoContainer container, Class<T> key, T implementation, Disposable parentDisposable) {
Object old = container.getComponentInstance(key);
container.unregisterComponent(key.getName());
container.registerComponentInstance(key.getName(), implementation);
Disposer.register(
parentDisposable,
() -> {
container.unregisterComponent(key.getName());
if (old != null) {
container.registerComponentInstance(key.getName(), old);
}
});
}
private static <T> void replaceComponentInstance(
ComponentManagerImpl componentManager,
Class<T> key,
T implementation,
Disposable parentDisposable) {
T old = componentManager.registerComponentInstance(key, implementation);
Disposer.register(parentDisposable, () -> componentManager.registerComponentInstance(key, old));
}
}