2016-11-10 32 views
6

Próbuję użyć zestawu SDK IntelliJ jako samodzielnego parsera java i działa on dobrze w większości przypadków, ale nie może rozwiązać problemu z typem zwrotnym.Rozdzielczość symboli w samodzielnym parserze IntelliJ

Kiedy debugowanie resolveMethod dla verify(mock).simpleMethod() w następnej próbki wewnątrz 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(); 
    } 

} 

widzę typ zwracanej verify(mock) jak IMethods i simpleMethod również rozwiązane poprawnie. Ale w moim wyniku zwracania parsera typ verify(mock) ma wartość T i simpleMethod z powodu tego niepowodzenia. Chyba nie mam żadnej usługi lub rozszerzenia, ale nie wiem, który.

Mój parser:

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

i wyjście:

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

Odpowiedz

6

W celu dokonania tej próbki do pracy musiałem dodać rt.jar poprzez projectEnvironment.addJarToClassPath(file); - niestety nadal jestem coraz awarii Rozwiązanie Metoda 2 w mockito i nie mogę utworzyć małej próbki, która powiela problem. Wciąż informacje o rt.jar mogą być przydatne dla kogoś, więc dodam je jako odpowiedź.

Funkcja zagadnień:

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

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

Mój obecny zrozumienie problemu: dowolny() return jest nazwą rodzajową i simpleMethod ma wiele przeciążeń i rozpoznawania nazw nie mógł odebrać prawidłowego jeden, ale sama idea jest w stanie wybrać odpowiedniego wariantu .

P.S. Po ustawieniu poziomu języka Java na 6 (jak w źródłach mockito) - nie ma już żadnych awarii.