title: Symbols resolution in standalone IntelliJ parser
body: <p>I'm trying to use IntelliJ SDK as standalone java parser and it works fine in most cases, but failing to resolve return type of generic methods.</p>
  
  <p>When I debugging <code>resolveMethod</code> for <code>verify(mock).simpleMethod()</code> in next sample inside of IntelliJ:</p>
  
  <pre><code>public class ResolutionTest {
  
      private interface IMethods {
          String simpleMethod();
      }
  
      private IMethods mock;
  
      public static &lt;T&gt; T verify(T m) {
          return m;
      }
  
      public void test() {
          verify(mock).simpleMethod();
      }
  
  }
  </code></pre>
  
  <p>I see return type of <code>verify(mock)</code> as <code>IMethods</code> and <code>simpleMethod</code> also resolved correctly. But in my parser return type of <code>verify(mock)</code> is <code>T</code> and <code>simpleMethod</code> resolution failing because of that. I guess I'm not register some service or extension but I cannot figure out which one.</p>
  
  <p>My parser:</p>
  
  <pre><code>import com.intellij.codeInsight.ContainerProvider;
  import com.intellij.codeInsight.runner.JavaMainMethodProvider;
  import com.intellij.core.CoreApplicationEnvironment;
  import com.intellij.core.CoreJavaFileManager;
  import com.intellij.core.JavaCoreApplicationEnvironment;
  import com.intellij.core.JavaCoreProjectEnvironment;
  import com.intellij.mock.MockProject;
  import com.intellij.openapi.Disposable;
  import com.intellij.openapi.components.ServiceManager;
  import com.intellij.openapi.extensions.Extensions;
  import com.intellij.openapi.extensions.ExtensionsArea;
  import com.intellij.openapi.fileTypes.FileTypeExtensionPoint;
  import com.intellij.openapi.vfs.VirtualFile;
  import com.intellij.psi.*;
  import com.intellij.psi.augment.PsiAugmentProvider;
  import com.intellij.psi.augment.TypeAnnotationModifier;
  import com.intellij.psi.compiled.ClassFileDecompilers;
  import com.intellij.psi.impl.JavaClassSupersImpl;
  import com.intellij.psi.impl.PsiElementFinderImpl;
  import com.intellij.psi.impl.PsiNameHelperImpl;
  import com.intellij.psi.impl.PsiTreeChangePreprocessor;
  import com.intellij.psi.impl.file.impl.JavaFileManager;
  import com.intellij.psi.meta.MetaDataContributor;
  import com.intellij.psi.search.GlobalSearchScope;
  import com.intellij.psi.stubs.BinaryFileStubBuilders;
  import com.intellij.psi.util.JavaClassSupers;
  
  import java.io.File;
  
  public class Main {
  
      static class Analyzer extends PsiElementVisitor {
          static final Disposable disposable = () -&gt; {
          };
  
          private static class ProjectEnvironment extends JavaCoreProjectEnvironment {
              public ProjectEnvironment(Disposable parentDisposable, CoreApplicationEnvironment applicationEnvironment) {
                  super(parentDisposable, applicationEnvironment);
              }
  
              @Override
              protected void registerJavaPsiFacade() {
                  JavaFileManager javaFileManager = getProject().getComponent(JavaFileManager.class);
                  CoreJavaFileManager coreJavaFileManager = (CoreJavaFileManager) javaFileManager;
                  ServiceManager.getService(getProject(), CoreJavaFileManager.class);
                  getProject().registerService(CoreJavaFileManager.class, coreJavaFileManager);
                  getProject().registerService(PsiNameHelper.class, PsiNameHelperImpl.getInstance());
                  PsiElementFinder finder = new PsiElementFinderImpl(getProject(), coreJavaFileManager);
                  ExtensionsArea area = Extensions.getArea(getProject());
                  area.getExtensionPoint(PsiElementFinder.EP_NAME).registerExtension(finder);
                  super.registerJavaPsiFacade();
              }
  
              @Override
              protected void preregisterServices() {
                  super.preregisterServices();
                  ExtensionsArea area = Extensions.getArea(getProject());
                  CoreApplicationEnvironment.registerExtensionPoint(area, PsiTreeChangePreprocessor.EP_NAME, PsiTreeChangePreprocessor.class);
                  CoreApplicationEnvironment.registerExtensionPoint(area, PsiElementFinder.EP_NAME, PsiElementFinder.class);
              }
          }
  
          private static class ApplicationEnvironment extends JavaCoreApplicationEnvironment {
  
              public ApplicationEnvironment(Disposable parentDisposable) {
                  super(parentDisposable);
                  myApplication.registerService(JavaClassSupers.class, new JavaClassSupersImpl());
              }
          }
  
          final ApplicationEnvironment applicationEnvironment;
          final ProjectEnvironment projectEnvironment;
  
          public Analyzer() {
              ExtensionsArea rootArea = Extensions.getRootArea();
              CoreApplicationEnvironment.registerExtensionPoint(rootArea, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint.class);
              CoreApplicationEnvironment.registerExtensionPoint(rootArea, FileContextProvider.EP_NAME, FileContextProvider.class);
              CoreApplicationEnvironment.registerExtensionPoint(rootArea, MetaDataContributor.EP_NAME, MetaDataContributor.class);
              CoreApplicationEnvironment.registerExtensionPoint(rootArea, PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
              CoreApplicationEnvironment.registerExtensionPoint(rootArea, JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
              CoreApplicationEnvironment.registerExtensionPoint(rootArea, ContainerProvider.EP_NAME, ContainerProvider.class);
              CoreApplicationEnvironment.registerExtensionPoint(rootArea, ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler.class);
              CoreApplicationEnvironment.registerExtensionPoint(rootArea, TypeAnnotationModifier.EP_NAME, TypeAnnotationModifier.class);
              applicationEnvironment = new ApplicationEnvironment(disposable);
              projectEnvironment = new ProjectEnvironment(disposable, applicationEnvironment);
          }
  
          public void add(final String[] args) throws Exception {
              for (String arg : args) {
                  final VirtualFile root = applicationEnvironment.getLocalFileSystem().findFileByIoFile(new File(arg));
                  projectEnvironment.addSourcesToClasspath(root);
              }
          }
  
  
          public void run() {
              MockProject project = projectEnvironment.getProject();
              PsiClass cls = project.getComponent(JavaFileManager.class)
                      .findClass("ResolutionTest", GlobalSearchScope.projectScope(project));
              if (cls != null) {
                  PsiMethod[] methods = cls.findMethodsByName("test", false);
                  if (methods.length == 1) {
                      PsiMethod method = methods[0];
                      for (PsiStatement s : method.getBody().getStatements()) {
                          System.out.println(s.getNode().getText());
                          process(s);
                      }
                  }
              }
          }
  
          private void process(PsiMethodCallExpression expression) {
              PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression();
              if (qualifierExpression instanceof PsiMethodCallExpression) {
                  process((PsiMethodCallExpression) qualifierExpression);
              } else if (qualifierExpression instanceof PsiReference) {
                  System.out.println("Resolving reference " + qualifierExpression.getText());
                  PsiElement targetElement = ((PsiReference) qualifierExpression).resolve();
                  if (targetElement == null) {
                      System.out.println("Resolution failed");
                  } else if (targetElement instanceof PsiClass) {
                      System.out.println("Class " + ((PsiClass) targetElement).getName());
                  } else if (targetElement instanceof PsiVariable) {
                      System.out.println("Variable " + ((PsiVariable) targetElement).getTypeElement().getText());
                  }
              }
  
              System.out.println("Resolving method " + expression.getMethodExpression().getText());
              PsiMethod method = expression.resolveMethod();
              if (method == null) {
                  System.out.println("Resolution failed");
              } else {
                  PsiClass clazz = method.getContainingClass();
                  System.out.println(clazz.getName() + "." + method.getName());
              }
          }
  
          private void process(PsiExpression e) {
              if (e instanceof PsiMethodCallExpression) {
                  process((PsiMethodCallExpression) e);
              }
          }
  
          private void process(PsiStatement s) {
              if (s instanceof PsiExpressionStatement) {
                  process(((PsiExpressionStatement) s).getExpression());
              }
          }
      }
  
      public static void main(String[] args) {
          try {
              Analyzer analyzer = new Analyzer();
              analyzer.add(args);
              analyzer.run();
          } catch (Exception e) {
              e.printStackTrace(System.out);
          }
      }
  }
  </code></pre>
  
  <p>And output:</p>
  
  <pre><code>verify(mock).simpleMethod();
  Resolving method verify
  ResolutionTest.verify
  Resolving method verify(mock).simpleMethod
  Resolution failed
  </code></pre>