2016-11-10 8 views
6

IntelliJ SDKをスタンドアロンのJavaパーサーとして使用しようとしていますが、ほとんどの場合は正常に動作しますが、汎用メソッドの戻り値タイプを解決できません。スタンドアロンIntelliJパーサーのシンボル解決

私はのIntelliJの内側に次のサンプルでverify(mock).simpleMethod()ため​​をデバッグ:

public class ResolutionTest { 

    private interface IMethods { 
     String simpleMethod(); 
    } 

    private IMethods mock; 

    public static <T> T verify(T m) { 
     return m; 
    } 

    public void test() { 
     verify(mock).simpleMethod(); 
    } 

} 

私はIMethodsとしてverify(mock)simpleMethodの戻り値の型も正しく解決ご覧ください。しかし、私のパーサーでは、verify(mock)の戻り値の型はTとなり、そのためにsimpleMethodの解像度が失敗します。私はいくつかのサービスやエクステンションを登録していないと思うけど、どれがどれかを理解することはできない。

マイパーサ:

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 =() -> { 
     }; 

     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); 
     } 
    } 
} 

そして出力:このサンプルが動作するようにするために

verify(mock).simpleMethod(); 
Resolving method verify 
ResolutionTest.verify 
Resolving method verify(mock).simpleMethod 
Resolution failed 

答えて

6

私はprojectEnvironment.addJarToClassPath(file);経由rt.jarを追加する必要がありました - 残念ながら私はまだ2つのメソッド解決の失敗を取得していますmockitoにあり、問題を再現する小さなサンプルを作成できません。 rt.jarについての情報は誰かに役立つかもしれないので、答えとして追加しています。問題と

機能:

@Test 
public void any_should_be_actual_alias_to_anyObject() { 
    mock.simpleMethod((Object) null); 

    verify(mock).simpleMethod(any()); 
    verify(mock).simpleMethod(anyObject()); 
} 

問題の私の現在の理解:任意の()の戻りが一般的でありかつsimpleMethodは、複数のオーバーロードし、適切なものを選ぶことができませんでしたリゾルバを持っていますが、アイデア自体は適切なバリアントを選択することができます。

P.S. Java言語レベルを6に設定した後(mockitoソースのように)、失敗はそれ以上ありません。

関連する問題