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