blob: cbb35b4f981242d47a0a306b18f8d585652528ab [file] [log] [blame]
/*
* Copyright 2000-2014 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.core;
import com.intellij.codeInsight.folding.CodeFoldingSettings;
import com.intellij.concurrency.*;
import com.intellij.lang.*;
import com.intellij.lang.impl.PsiBuilderFactoryImpl;
import com.intellij.mock.MockApplication;
import com.intellij.mock.MockApplicationEx;
import com.intellij.mock.MockFileDocumentManagerImpl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.impl.CoreCommandProcessor;
import com.intellij.openapi.components.ExtensionAreas;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.ExtensionsArea;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.*;
import com.intellij.openapi.progress.*;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.openapi.vfs.encoding.EncodingRegistry;
import com.intellij.openapi.vfs.impl.CoreVirtualFilePointerManager;
import com.intellij.openapi.vfs.impl.VirtualFileManagerImpl;
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem;
import com.intellij.openapi.vfs.local.CoreLocalFileSystem;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
import com.intellij.psi.FileContextProvider;
import com.intellij.psi.PsiReferenceService;
import com.intellij.psi.PsiReferenceServiceImpl;
import com.intellij.psi.impl.meta.MetaRegistry;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl;
import com.intellij.psi.meta.MetaDataContributor;
import com.intellij.psi.meta.MetaDataRegistrar;
import com.intellij.psi.stubs.BinaryFileStubBuilders;
import com.intellij.psi.stubs.CoreStubTreeLoader;
import com.intellij.psi.stubs.StubTreeLoader;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.messages.MessageBusFactory;
import org.jetbrains.annotations.NotNull;
import org.picocontainer.MutablePicoContainer;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* @author yole
*/
public class CoreApplicationEnvironment {
private final CoreFileTypeRegistry myFileTypeRegistry;
protected final MockApplication myApplication;
private final CoreLocalFileSystem myLocalFileSystem;
protected final VirtualFileSystem myJarFileSystem;
@NotNull private final Disposable myParentDisposable;
public CoreApplicationEnvironment(@NotNull Disposable parentDisposable) {
myParentDisposable = parentDisposable;
Extensions.cleanRootArea(myParentDisposable);
myFileTypeRegistry = new CoreFileTypeRegistry();
CoreEncodingRegistry encodingRegistry = new CoreEncodingRegistry();
myApplication = createApplication(myParentDisposable);
ApplicationManager.setApplication(myApplication,
new StaticGetter<FileTypeRegistry>(myFileTypeRegistry),
new StaticGetter<EncodingRegistry>(encodingRegistry),
myParentDisposable);
myLocalFileSystem = createLocalFileSystem();
myJarFileSystem = createJarFileSystem();
Extensions.registerAreaClass(ExtensionAreas.IDEA_PROJECT, null);
final MutablePicoContainer appContainer = myApplication.getPicoContainer();
registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl(new Function<CharSequence, Document>() {
@Override
public Document fun(CharSequence charSequence) {
return new DocumentImpl(charSequence);
}
}, null));
VirtualFileSystem[] fs = {myLocalFileSystem, myJarFileSystem};
VirtualFileManagerImpl virtualFileManager = new VirtualFileManagerImpl(fs, MessageBusFactory.newMessageBus(myApplication));
registerComponentInstance(appContainer, VirtualFileManager.class, virtualFileManager);
registerApplicationService(VirtualFilePointerManager.class, createVirtualFilePointerManager());
registerApplicationService(DefaultASTFactory.class, new CoreASTFactory());
registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl());
registerApplicationService(ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl());
registerApplicationService(StubTreeLoader.class, new CoreStubTreeLoader());
registerApplicationService(PsiReferenceService.class, new PsiReferenceServiceImpl());
registerApplicationService(MetaDataRegistrar.class, new MetaRegistry());
registerApplicationExtensionPoint(ContentBasedFileSubstitutor.EP_NAME, ContentBasedFileSubstitutor.class);
registerExtensionPoint(Extensions.getRootArea(), BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint.class);
registerExtensionPoint(Extensions.getRootArea(), FileContextProvider.EP_NAME, FileContextProvider.class);
registerApplicationExtensionPoint(MetaDataContributor.EP_NAME, MetaDataContributor.class);
ProgressIndicatorProvider.ourInstance = createProgressIndicatorProvider();
registerApplicationService(JobLauncher.class, createJobLauncher());
registerApplicationService(CodeFoldingSettings.class, new CodeFoldingSettings());
registerApplicationService(CommandProcessor.class, new CoreCommandProcessor());
}
public <T> void registerApplicationService(@NotNull Class<T> serviceInterface, @NotNull T serviceImplementation) {
myApplication.registerService(serviceInterface, serviceImplementation);
}
@NotNull
protected VirtualFilePointerManager createVirtualFilePointerManager() {
return new CoreVirtualFilePointerManager();
}
@NotNull
protected MockApplication createApplication(@NotNull Disposable parentDisposable) {
return new MockApplicationEx(parentDisposable);
}
@NotNull
protected JobLauncher createJobLauncher() {
return new JobLauncher() {
@Override
public <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<? extends T> things,
ProgressIndicator progress,
boolean failFastOnAcquireReadAction,
@NotNull Processor<T> thingProcessor) throws ProcessCanceledException {
for (T thing : things) {
if (!thingProcessor.process(thing))
return false;
}
return true;
}
@Override
public <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<? extends T> things,
ProgressIndicator progress,
boolean runInReadAction,
boolean failFastOnAcquireReadAction,
@NotNull Processor<T> thingProcessor) {
return invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor);
}
@NotNull
@Override
public <T> AsyncFuture<Boolean> invokeConcurrentlyUnderProgressAsync(@NotNull List<? extends T> things,
ProgressIndicator progress,
boolean failFastOnAcquireReadAction,
@NotNull Processor<T> thingProcessor) {
return AsyncUtil.wrapBoolean(invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor));
}
@NotNull
@Override
public Job<Void> submitToJobThread(int priority, @NotNull Runnable action, Consumer<Future> onDoneCallback) {
action.run();
if (onDoneCallback != null)
onDoneCallback.consume(new Future() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return true;
}
@Override
public Object get() {
return null;
}
@Override
public Object get(long timeout, @NotNull TimeUnit unit) {
return null;
}
});
return Job.NULL_JOB;
}
};
}
@NotNull
protected ProgressIndicatorProvider createProgressIndicatorProvider() {
return new ProgressIndicatorProvider() {
@Override
public ProgressIndicator getProgressIndicator() {
return new EmptyProgressIndicator();
}
@Override
protected void doCheckCanceled() throws ProcessCanceledException {
}
@NotNull
@Override
public NonCancelableSection startNonCancelableSection() {
return NonCancelableSection.EMPTY;
}
};
}
@NotNull
protected VirtualFileSystem createJarFileSystem() {
return new CoreJarFileSystem();
}
@NotNull
protected CoreLocalFileSystem createLocalFileSystem() {
return new CoreLocalFileSystem();
}
@NotNull
public MockApplication getApplication() {
return myApplication;
}
@NotNull
public Disposable getParentDisposable() {
return myParentDisposable;
}
public <T> void registerApplicationComponent(@NotNull Class<T> interfaceClass, @NotNull T implementation) {
registerComponentInstance(myApplication.getPicoContainer(), interfaceClass, implementation);
}
public void registerFileType(@NotNull FileType fileType, @NotNull String extension) {
myFileTypeRegistry.registerFileType(fileType, extension);
}
public void registerParserDefinition(@NotNull ParserDefinition definition) {
addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition);
}
public static <T> void registerComponentInstance(@NotNull MutablePicoContainer container, @NotNull Class<T> key, @NotNull T implementation) {
container.unregisterComponent(key);
container.registerComponentInstance(key, implementation);
}
public <T> void addExplicitExtension(@NotNull LanguageExtension<T> instance, @NotNull Language language, @NotNull T object) {
doAddExplicitExtension(instance, language, object);
}
public void registerParserDefinition(@NotNull Language language, @NotNull ParserDefinition parserDefinition) {
addExplicitExtension(LanguageParserDefinitions.INSTANCE, language, parserDefinition);
}
public <T> void addExplicitExtension(@NotNull final FileTypeExtension<T> instance, @NotNull final FileType fileType, @NotNull final T object) {
doAddExplicitExtension(instance, fileType, object);
}
private <T,U> void doAddExplicitExtension(@NotNull final KeyedExtensionCollector<T,U> instance, @NotNull final U key, @NotNull final T object) {
instance.addExplicitExtension(key, object);
Disposer.register(myParentDisposable, new Disposable() {
@Override
public void dispose() {
instance.removeExplicitExtension(key, object);
}
});
}
public <T> void addExplicitExtension(@NotNull final ClassExtension<T> instance, @NotNull final Class aClass, @NotNull final T object) {
doAddExplicitExtension(instance, aClass, object);
}
public <T> void addExtension(@NotNull ExtensionPointName<T> name, @NotNull final T extension) {
final ExtensionPoint<T> extensionPoint = Extensions.getRootArea().getExtensionPoint(name);
extensionPoint.registerExtension(extension);
Disposer.register(myParentDisposable, new Disposable() {
@Override
public void dispose() {
extensionPoint.unregisterExtension(extension);
}
});
}
public static <T> void registerExtensionPoint(@NotNull ExtensionsArea area,
@NotNull ExtensionPointName<T> extensionPointName,
@NotNull Class<? extends T> aClass) {
final String name = extensionPointName.getName();
registerExtensionPoint(area, name, aClass);
}
public static <T> void registerExtensionPoint(@NotNull ExtensionsArea area, @NotNull String name, @NotNull Class<? extends T> aClass) {
if (!area.hasExtensionPoint(name)) {
ExtensionPoint.Kind kind = aClass.isInterface() || (aClass.getModifiers() & Modifier.ABSTRACT) != 0 ? ExtensionPoint.Kind.INTERFACE : ExtensionPoint.Kind.BEAN_CLASS;
area.registerExtensionPoint(name, aClass.getName(), kind);
}
}
public static <T> void registerApplicationExtensionPoint(@NotNull ExtensionPointName<T> extensionPointName, @NotNull Class<? extends T> aClass) {
final String name = extensionPointName.getName();
registerExtensionPoint(Extensions.getRootArea(), name, aClass);
}
@NotNull
public CoreLocalFileSystem getLocalFileSystem() {
return myLocalFileSystem;
}
@NotNull
public VirtualFileSystem getJarFileSystem() {
return myJarFileSystem;
}
}