2016-11-10 83 views
6

我试图使用IntelliJ SDK作为独立的Java解析器,它在大多数情况下工作正常,但未能解析返回类型的泛型方法。独立IntelliJ语法分析器中的符号解析

当我下一个样品调试​​为verify(mock).simpleMethod()的IntelliJ内:

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

} 

我看到的verify(mock)返回类型为IMethodssimpleMethod也正确地解析。但在我的解析器返回类型verify(mock)TsimpleMethod分辨率因此而失败。我想我没有注册一些服务或扩展,但我不知道哪一个。

我的解析器:

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

为了使这个样品工作,我不得不rt.jar通过projectEnvironment.addJarToClassPath(file);加 - 遗憾的是,我仍然得到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源代码中)之后 - 没有更多的失败。

相关问题