java - Symbols resolution in standalone IntelliJ parser -
i'm trying use intellij sdk standalone java parser , works fine in cases, failing resolve return type of generic methods.
when debugging resolvemethod
verify(mock).simplemethod()
in next sample inside of 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(); } }
i see return type of verify(mock)
imethods
, simplemethod
resolved correctly. in parser return type of verify(mock)
t
, simplemethod
resolution failing because of that. guess i'm not register service or extension cannot figure out one.
my 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 { (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]; (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); } } }
and output:
verify(mock).simplemethod(); resolving method verify resolutiontest.verify resolving method verify(mock).simplemethod resolution failed
in order make sample work had add rt.jar
via projectenvironment.addjartoclasspath(file);
- unfortunately i'm still getting 2 method resolution failures in mockito , i'm unable create small sample reproduces issue. still information rt.jar
useful i'm adding answer.
function issues:
@test public void any_should_be_actual_alias_to_anyobject() { mock.simplemethod((object) null); verify(mock).simplemethod(any()); verify(mock).simplemethod(anyobject()); }
my current understanding of issue: any() return generic , simplemethod has multiple overloads , resolver not pick proper one, idea able select proper variant.
p.s. after setting java language level 6 (as in mockito sources) – there no more failures.
Comments
Post a Comment