/* * 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.core; import com.intellij.concurrency.*; import com.intellij.lang.*; import com.intellij.lang.impl.PsiBuilderFactoryImpl; import com.intellij.mock.MockApplication; import com.intellij.mock.MockFileDocumentManagerImpl; import com.intellij.mock.MockReferenceProvidersRegistry; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; 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.Disposer; import com.intellij.openapi.util.StaticGetter; 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.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.impl.MessageBusImpl; import org.jetbrains.annotations.NotNull; import org.picocontainer.MutablePicoContainer; import java.lang.reflect.Modifier; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * @author yole */ public class CoreApplicationEnvironment { private final CoreFileTypeRegistry myFileTypeRegistry; private final CoreEncodingRegistry myEncodingRegistry; protected final MockApplication myApplication; private final CoreLocalFileSystem myLocalFileSystem; protected final VirtualFileSystem myJarFileSystem; private final Disposable myParentDisposable; public CoreApplicationEnvironment(Disposable parentDisposable) { myParentDisposable = parentDisposable; Extensions.cleanRootArea(myParentDisposable); myFileTypeRegistry = new CoreFileTypeRegistry(); myEncodingRegistry = new CoreEncodingRegistry(); myApplication = createApplication(myParentDisposable); ApplicationManager.setApplication(myApplication, new StaticGetter<FileTypeRegistry>(myFileTypeRegistry), new StaticGetter<EncodingRegistry>(myEncodingRegistry), 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, new MessageBusImpl(myApplication, null)); registerComponentInstance(appContainer, VirtualFileManager.class, virtualFileManager); registerApplicationService(VirtualFilePointerManager.class, createVirtualFilePointerManager()); myApplication.registerService(DefaultASTFactory.class, new CoreASTFactory()); myApplication.registerService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl()); myApplication.registerService(ReferenceProvidersRegistry.class, new MockReferenceProvidersRegistry()); myApplication.registerService(StubTreeLoader.class, new CoreStubTreeLoader()); myApplication.registerService(PsiReferenceService.class, new PsiReferenceServiceImpl()); myApplication.registerService(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(); myApplication.registerService(JobLauncher.class, createJobLauncher()); } public <T> void registerApplicationService(Class<T> serviceInterface, T serviceImplementation) { myApplication.registerService(serviceInterface, serviceImplementation); } protected VirtualFilePointerManager createVirtualFilePointerManager() { return new CoreVirtualFilePointerManager(); } protected MockApplication createApplication(Disposable parentDisposable) { return new MockApplication(parentDisposable); } 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) { final AsyncFutureResult<Boolean> asyncFutureResult = AsyncFutureFactory.getInstance().createAsyncFutureResult(); try { final boolean result = invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor); asyncFutureResult.set(result); } catch (Throwable t) { asyncFutureResult.setException(t); } return asyncFutureResult; } @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() throws InterruptedException, ExecutionException { return null; } @Override public Object get(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return null; } }); return Job.NULL_JOB; } }; } protected ProgressIndicatorProvider createProgressIndicatorProvider() { return new ProgressIndicatorProvider() { @Override public ProgressIndicator getProgressIndicator() { return new EmptyProgressIndicator(); } @Override protected void doCheckCanceled() throws ProcessCanceledException { } @Override public NonCancelableSection startNonCancelableSection() { return NonCancelableSection.EMPTY; } }; } protected VirtualFileSystem createJarFileSystem() { return new CoreJarFileSystem(); } protected CoreLocalFileSystem createLocalFileSystem() { return new CoreLocalFileSystem(); } public MockApplication getApplication() { return myApplication; } public Disposable getParentDisposable() { return myParentDisposable; } public <T> void registerApplicationComponent(final Class<T> interfaceClass, final T implementation) { registerComponentInstance(myApplication.getPicoContainer(), interfaceClass, implementation); } public void registerFileType(FileType fileType, String extension) { myFileTypeRegistry.registerFileType(fileType, extension); } public void registerParserDefinition(ParserDefinition definition) { addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition); } public static <T> void registerComponentInstance(final MutablePicoContainer container, final Class<T> key, final T implementation) { container.unregisterComponent(key); container.registerComponentInstance(key, implementation); } public <T> void addExplicitExtension(final LanguageExtension<T> instance, final Language language, final T object) { instance.addExplicitExtension(language, object); Disposer.register(myParentDisposable, new Disposable() { @Override public void dispose() { instance.removeExplicitExtension(language, object); } }); } public void registerParserDefinition(Language language, ParserDefinition parserDefinition) { addExplicitExtension(LanguageParserDefinitions.INSTANCE, language, parserDefinition); } public <T> void addExplicitExtension(final FileTypeExtension<T> instance, final FileType fileType, final T object) { instance.addExplicitExtension(fileType, object); Disposer.register(myParentDisposable, new Disposable() { @Override public void dispose() { instance.removeExplicitExtension(fileType, object); } }); } public <T> void addExtension(ExtensionPointName<T> name, 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(final ExtensionsArea area, final ExtensionPointName<T> extensionPointName, final Class<? extends T> aClass) { final String name = extensionPointName.getName(); registerExtensionPoint(area, name, aClass); } public static <T> void registerExtensionPoint(ExtensionsArea area, String name, 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(final ExtensionPointName<T> extensionPointName, final Class<? extends T> aClass) { final String name = extensionPointName.getName(); registerExtensionPoint(Extensions.getRootArea(), name, aClass); } public CoreLocalFileSystem getLocalFileSystem() { return myLocalFileSystem; } public VirtualFileSystem getJarFileSystem() { return myJarFileSystem; } }