/* * 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(myFileTypeRegistry), new StaticGetter(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() { @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 void registerApplicationService(@NotNull Class 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 boolean invokeConcurrentlyUnderProgress(@NotNull List things, ProgressIndicator progress, boolean failFastOnAcquireReadAction, @NotNull Processor thingProcessor) throws ProcessCanceledException { for (T thing : things) { if (!thingProcessor.process(thing)) return false; } return true; } @Override public boolean invokeConcurrentlyUnderProgress(@NotNull List things, ProgressIndicator progress, boolean runInReadAction, boolean failFastOnAcquireReadAction, @NotNull Processor thingProcessor) { return invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor); } @NotNull @Override public AsyncFuture invokeConcurrentlyUnderProgressAsync(@NotNull List things, ProgressIndicator progress, boolean failFastOnAcquireReadAction, @NotNull Processor thingProcessor) { return AsyncUtil.wrapBoolean(invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor)); } @NotNull @Override public Job submitToJobThread(int priority, @NotNull Runnable action, Consumer 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 void registerApplicationComponent(@NotNull Class 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 void registerComponentInstance(@NotNull MutablePicoContainer container, @NotNull Class key, @NotNull T implementation) { container.unregisterComponent(key); container.registerComponentInstance(key, implementation); } public void addExplicitExtension(@NotNull LanguageExtension 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 void addExplicitExtension(@NotNull final FileTypeExtension instance, @NotNull final FileType fileType, @NotNull final T object) { doAddExplicitExtension(instance, fileType, object); } private void doAddExplicitExtension(@NotNull final KeyedExtensionCollector 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 void addExplicitExtension(@NotNull final ClassExtension instance, @NotNull final Class aClass, @NotNull final T object) { doAddExplicitExtension(instance, aClass, object); } public void addExtension(@NotNull ExtensionPointName name, @NotNull final T extension) { final ExtensionPoint extensionPoint = Extensions.getRootArea().getExtensionPoint(name); extensionPoint.registerExtension(extension); Disposer.register(myParentDisposable, new Disposable() { @Override public void dispose() { extensionPoint.unregisterExtension(extension); } }); } public static void registerExtensionPoint(@NotNull ExtensionsArea area, @NotNull ExtensionPointName extensionPointName, @NotNull Class aClass) { final String name = extensionPointName.getName(); registerExtensionPoint(area, name, aClass); } public static void registerExtensionPoint(@NotNull ExtensionsArea area, @NotNull String name, @NotNull Class 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 void registerApplicationExtensionPoint(@NotNull ExtensionPointName extensionPointName, @NotNull Class aClass) { final String name = extensionPointName.getName(); registerExtensionPoint(Extensions.getRootArea(), name, aClass); } @NotNull public CoreLocalFileSystem getLocalFileSystem() { return myLocalFileSystem; } @NotNull public VirtualFileSystem getJarFileSystem() { return myJarFileSystem; } }