Package org.intellij.grammar

Source Code of org.intellij.grammar.LightPsi

/*
* Copyright 2011-2014 Gregory Shrago
*
* 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 org.intellij.grammar;

import com.intellij.concurrency.AsyncFutureFactory;
import com.intellij.concurrency.AsyncFutureFactoryImpl;
import com.intellij.concurrency.JobLauncher;
import com.intellij.concurrency.JobLauncherImpl;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.lang.*;
import com.intellij.lang.impl.PsiBuilderFactoryImpl;
import com.intellij.lang.impl.PsiBuilderImpl;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.lexer.Lexer;
import com.intellij.mock.*;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
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.fileEditor.impl.FileDocumentManagerImpl;
import com.intellij.openapi.fileTypes.FileTypeFactory;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.openapi.options.SchemesManagerFactory;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.DumbServiceImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.intellij.openapi.vfs.encoding.EncodingManagerImpl;
import com.intellij.openapi.vfs.encoding.EncodingRegistry;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiCachedValuesFactory;
import com.intellij.psi.impl.PsiFileFactoryImpl;
import com.intellij.psi.impl.search.CachesBasedRefSearcher;
import com.intellij.psi.impl.search.PsiSearchHelperImpl;
import com.intellij.psi.impl.source.CharTableImpl;
import com.intellij.psi.impl.source.resolve.ResolveCache;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.testFramework.MockSchemesManagerFactory;
import com.intellij.util.CachedValuesManagerImpl;
import com.intellij.util.Function;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusFactory;
import org.intellij.grammar.java.JavaHelper;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.picocontainer.*;
import org.picocontainer.defaults.AbstractComponentAdapter;

import java.io.*;
import java.lang.reflect.Modifier;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @author greg
*/
public class LightPsi {

  private static final MyParsing ourParsing;

  static {
    try {
      ourParsing = new MyParsing();
    }
    catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public static PsiFile parseFile(File file, ParserDefinition parserDefinition) throws IOException {
    String name = file.getName();
    String text = FileUtil.loadFile(file);
    return parseFile(name, text, parserDefinition);
  }

  public static PsiFile parseFile(String name, @NotNull String text, @NotNull ParserDefinition parserDefinition) {
    return ourParsing.createFile(name, text, parserDefinition);
  }

  public static ASTNode parseText(@NotNull String text, @NotNull ParserDefinition parserDefinition) {
    return ourParsing.createAST(text, parserDefinition);
  }

  /*
   * Builds light-psi-all.jar from JVM class loader log (-verbose:class option)
   */
  public static void main(String[] args) throws Throwable {
    if (args.length < 2) {
      System.out.println("Usage: Main <output-dir> <classes.log.txt>");
      return;
    }

    File dir = new File(args[0]);
    BufferedReader reader = new BufferedReader(new FileReader(new File(args[1])));
    String s;
    Pattern pattern = Pattern.compile("\\[Loaded (.*) from (?:file:)?(.*)\\]");

    JarOutputStream jarFile = new JarOutputStream(new FileOutputStream(new File(dir, "light-psi-all.jar")));
//    JarOutputStream jarFile = new JarOutputStream(new FileOutputStream(new File(dir, "light-psi-min.jar")));
    addJarEntry(jarFile, "misc/registry.properties");
    while ((s = reader.readLine()) != null) {
      Matcher matcher = pattern.matcher(s);
      if (!matcher.matches()) continue;
      String className = matcher.group(1);
      String path = matcher.group(2);
      if (!path.startsWith("/Applications")) continue;
//      if (!path.contains("light-psi-all.jar")) continue;
      addJarEntry(jarFile, className.replace(".", "/") + ".class");
    }
    jarFile.close();
  }

  private static void addJarEntry(JarOutputStream jarFile, String resourceName) throws IOException {
    InputStream stream = LightPsi.class.getClassLoader().getResourceAsStream(resourceName);
    if (stream == null) {
      System.err.println("Skipping missing " + resourceName);
    }
    else {
      jarFile.putNextEntry(new JarEntry(resourceName));
      FileUtil.copy(stream, jarFile);
      jarFile.closeEntry();
    }
  }

  private static class MyParsing implements Disposable {

    private final Trinity<MockProjectEx,MockPsiManager,PsiFileFactoryImpl> myModel;

    MyParsing() throws Exception {
      myModel = Init.initPsiFileFactory(this);
      Init.initExtensions(getProject(), myModel.second);
    }

    protected PsiFile createFile(@NonNls String name, @NotNull String text, @NotNull ParserDefinition definition) {
      Language language = definition.getFileNodeType().getLanguage();
      Init.addExplicitExtension(getProject(), LanguageParserDefinitions.INSTANCE, language, definition);
      return myModel.third.trySetupPsiForFile(new LightVirtualFile(name, language, text), language, true, false);
    }

    protected ASTNode createAST(@NotNull String text, @NotNull ParserDefinition definition) {
      PsiParser parser = definition.createParser(getProject());
      Lexer lexer = definition.createLexer(getProject());
      PsiBuilderImpl psiBuilder = new PsiBuilderImpl(getProject(), null, definition, lexer, new CharTableImpl(), text, null, null);
      return parser.parse(definition.getFileNodeType(), psiBuilder);
    }

    private MockProjectEx getProject() {
      return myModel.first;
    }

    @Override
    public void dispose() {
    }
  }

  public static class Init {

    public static void initExtensions(MockProjectEx project, MockPsiManager psiManager) {
      Extensions.getRootArea().registerExtensionPoint("com.intellij.referencesSearch", "com.intellij.util.QueryExecutor");
      Extensions.getRootArea().registerExtensionPoint("com.intellij.useScopeEnlarger", "com.intellij.psi.search.UseScopeEnlarger");
      Extensions.getRootArea().registerExtensionPoint("com.intellij.languageInjector", "com.intellij.psi.LanguageInjector");
      Extensions.getArea(project).registerExtensionPoint("com.intellij.multiHostInjector", "com.intellij.lang.injection.MultiHostInjector");
      Extensions.getRootArea().registerExtensionPoint("com.intellij.codeInsight.containerProvider",
                                                      "com.intellij.codeInsight.ContainerProvider");
      Extensions.getRootArea().getExtensionPoint("com.intellij.referencesSearch").registerExtension(new CachesBasedRefSearcher());
      registerApplicationService(project, PsiReferenceService.class, new PsiReferenceServiceImpl());
      registerApplicationService(project, JobLauncher.class, new JobLauncherImpl());
      registerApplicationService(project, AsyncFutureFactory.class, new AsyncFutureFactoryImpl());
      project.registerService(PsiSearchHelper.class, new PsiSearchHelperImpl(psiManager));
      project.registerService(DumbService.class, new DumbServiceImpl(project));
      project.registerService(ResolveCache.class, new ResolveCache(project.getMessageBus()));
      project.registerService(PsiFileFactory.class, new PsiFileFactoryImpl(psiManager));
      try {
        project.registerService(JavaHelper.class, new JavaHelper.AsmHelper());
      }
      catch (LinkageError e) {
        System.out.println("ASM not available, using reflection helper: " + e);
        project.registerService(JavaHelper.class, new JavaHelper.ReflectionHelper());
      }

      InjectedLanguageManagerImpl languageManager = new InjectedLanguageManagerImpl(project, DumbService.getInstance(project));
      Disposer.register(project, languageManager);
      project.registerService(InjectedLanguageManager.class, languageManager);
      ProgressManager.getInstance();
    }

    private static <T> void registerApplicationService(Project project, final Class<T> aClass, T object) {
      final MockApplicationEx application = (MockApplicationEx)ApplicationManager.getApplication();
      application.registerService(aClass, object);
      Disposer.register(project, new Disposable() {
        @Override
        public void dispose() {
          application.getPicoContainer().unregisterComponent(aClass.getName());
        }
      });
    }
   
    public static Trinity<MockProjectEx, MockPsiManager, PsiFileFactoryImpl> initPsiFileFactory(Disposable rootDisposable) {
      final MockApplicationEx application = initApplication(rootDisposable);
      ComponentAdapter component = application.getPicoContainer().getComponentAdapter(ProgressManager.class.getName());
      if (component == null) {
        application.getPicoContainer().registerComponent(new AbstractComponentAdapter(ProgressManager.class.getName(), Object.class) {
          @Override
          public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException {
            return new ProgressManagerImpl();
          }

          @Override
          public void verify(PicoContainer container) throws PicoIntrospectionException {
          }
        });
      }
      Extensions.registerAreaClass("IDEA_PROJECT", null);
      MockProjectEx project = new MockProjectEx(rootDisposable);
      MockPsiManager psiManager = new MockPsiManager(project);
      PsiFileFactoryImpl psiFileFactory = new PsiFileFactoryImpl(psiManager);
      MutablePicoContainer appContainer = application.getPicoContainer();
      registerComponentInstance(appContainer, MessageBus.class, MessageBusFactory.newMessageBus(application));
      registerComponentInstance(appContainer, SchemesManagerFactory.class, new MockSchemesManagerFactory());
      final MockEditorFactory editorFactory = new MockEditorFactory();
      registerComponentInstance(appContainer, EditorFactory.class, editorFactory);
      registerComponentInstance(
        appContainer, FileDocumentManager.class,
        new MockFileDocumentManagerImpl(new Function<CharSequence, Document>() {
          @Override
          public Document fun(CharSequence charSequence) {
            return editorFactory.createDocument(charSequence);
          }
        }, FileDocumentManagerImpl.HARD_REF_TO_DOCUMENT_KEY)
      );
      registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager());
      registerComponentInstance(appContainer, FileTypeManager.class, new MockFileTypeManager(new MockLanguageFileType(PlainTextLanguage.INSTANCE, "txt")));
      registerApplicationService(project, PsiBuilderFactory.class, new PsiBuilderFactoryImpl());
      registerApplicationService(project, DefaultASTFactory.class, new DefaultASTFactoryImpl());
      registerApplicationService(project, ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl());
      project.registerService(CachedValuesManager.class, new CachedValuesManagerImpl(project, new PsiCachedValuesFactory(psiManager)));
      project.registerService(PsiManager.class, psiManager);
      project.registerService(StartupManager.class, new StartupManagerImpl(project));
      registerExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class);
      return Trinity.create(project, psiManager, psiFileFactory);
    }

    public static MockApplicationEx initApplication(Disposable rootDisposable) {
      MockApplicationEx instance = new MockApplicationEx(rootDisposable);
      ApplicationManager.setApplication(
        instance,
        new Getter<FileTypeRegistry>() {
          @Override
          public FileTypeRegistry get() {
            return FileTypeManager.getInstance();
          }
        },
        new Getter<EncodingRegistry>() {
          @Override
          public EncodingRegistry get() {
            return EncodingManager.getInstance();
          }
        },
        rootDisposable
      );
      instance.registerService(EncodingManager.class, EncodingManagerImpl.class);
      return instance;
    }

    public static <T> void registerExtensionPoint(ExtensionPointName<T> extensionPointName, final Class<T> aClass) {
      registerExtensionPoint(Extensions.getRootArea(), extensionPointName, aClass);
    }

    public static <T> void registerExtensionPoint(ExtensionsArea area, ExtensionPointName<T> extensionPointName, Class<? extends T> aClass) {
      final String name = extensionPointName.getName();
      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> T registerComponentInstance(MutablePicoContainer container, Class<T> key, T implementation) {
      Object old = container.getComponentInstance(key);
      container.unregisterComponent(key);
      container.registerComponentInstance(key, implementation);
      return (T)old;
    }

    public static <T> void addExplicitExtension(Project project, final LanguageExtension<T> instance, final Language language, final T object) {
      instance.addExplicitExtension(language, object);
      Disposer.register(project, new Disposable() {
        @Override
        public void dispose() {
          instance.removeExplicitExtension(language, object);
        }
      });
    }
  }
}
TOP

Related Classes of org.intellij.grammar.LightPsi

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.