How to create an IntelliJ project taht can resolve types the jdk standard library
UPDATE : I think figured it out, but will be glad to hear any comments about the way I use the platform. See solution below.
-----------------------------
ORIGINAL:
Hello,
I create an application that uses IntelliJ for its code insight and parsing capabilities.
So I create an IdeaTestApplication instance.
I cannot get IntelliJ to figure out the paths of the JDK.
In the example, I have a field f of type List<Integer>. The type of f cannot be resolved.
I expect f.getType().getCannonicalText() to retrieve: "java.util.List<java.lang.Integer>"
But it actually is: "List<Integer>"
I suspect that I do not setup the project's JDK properly.
I am allowed to use internal classes of IntelliJ - i.e., such that are not part of the OpenAPI.
import com.intellij.ide.impl.NewProjectUtil;
import com.intellij.idea.IdeaTestApplication;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkType;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.testFramework.PsiTestUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class CleanCreateProject {
private static Project createAnOpenProject(String projectName, String projectRoot) {
final ProjectManagerEx myProjectManager = ProjectManagerEx.getInstanceEx();
final Project project = myProjectManager.newProject(projectName, projectRoot, true, false);
myProjectManager.openProject(project);
return project;
}
public static void main(String[] args){
IdeaTestApplication.getInstance(null);
new WriteAction<Integer>() {
@Override
protected void run(@NotNull Result<Integer> result) {
Project project = createAnOpenProject("myProject", root());
setupJdk(project);
ModuleType moduleType = JavaModuleType.getModuleType();
Module module = ModuleManager.getInstance(project).newModule(moduleIMLPath(), moduleType.getId());
PsiTestUtil.addSourceContentToRoots(module,
Objects.requireNonNull(LocalFileSystem.getInstance().findFileByPath(srcRoot())),
false);
showProblem(project);
result.setResult(0);
}
}.execute();
}
private static void showProblem(Project project) {
for(VirtualFile virtualFile: FilenameIndex.getAllFilesByExt(project, "java")){
PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
for(PsiClass cls: ((PsiClassOwner)psiFile).getClasses()){
System.out.println("cls.getName() = " + cls.getName());
PsiField f = cls.findFieldByName("f", false);
System.out.println("f.getType().getCanonicalText() = " + f.getType().getCanonicalText());
}
}
}
public static void setupJdk(Project project) {
Sdk jdk = JavaSdk.getInstance().createJdk("java 1.8", jdkHomeDirectory(), false);
ProjectJdkTable.getInstance().addJdk(jdk);
ProjectRootManager.getInstance(project).setProjectSdk(jdk);
NewProjectUtil.applyJdkToProject(project, jdk);
for(SdkType t: SdkType.getAllTypes()){
assert t.getName().equals("JavaSDK");
t.setupSdkPaths(jdk);
break;
}
}
private static String jdkHomeDirectory() {
return "/usr/lib/jvm/jdk1.8.0_181";
}
private static String root() {
return "/tmp/projectRoot";
}
private static String srcRoot() {
return root() + "/src";
}
private static String moduleIMLPath() {
return root() + "/file.iml";
}
}
In my file system, the contents of the java file is:
import java.util.List;
class A{
List<Integer> f;
}
--------------------
SOLUTION:
What I did is to setup the Jdk for each module, by adding the following lines:
Module[] modules = ModuleManager.getInstance(project).getModules();
for (Module module : modules) {
ModuleRootModificationUtil.setModuleSdk(module, jdk);
}
Overall, here is the working example:
package playground;
import com.intellij.ide.impl.NewProjectUtil;
import com.intellij.idea.IdeaTestApplication;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.PsiTestUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class ShowProblem {
private static Project createAnOpenProject(String projectName, String projectRoot) {
final ProjectManagerEx myProjectManager = ProjectManagerEx.getInstanceEx();
final Project project = myProjectManager.newProject(projectName, projectRoot, true, false);
myProjectManager.openProject(project);
return project;
}
public static void main(String[] args){
IdeaTestApplication.getInstance(null);
new WriteAction<Integer>() {
@Override
protected void run(@NotNull Result<Integer> result) {
Project project = createAnOpenProject("myProject", root());
ModuleType moduleType = JavaModuleType.getModuleType();
Module module = ModuleManager.getInstance(project).newModule(moduleIMLPath(), moduleType.getId());
PsiTestUtil.addSourceContentToRoots(module,
Objects.requireNonNull(LocalFileSystem.getInstance().findFileByPath(srcRoot())),
false);
setupJdk(project);
showProblem(project);
result.setResult(0);
}
}.execute();
}
private static void showProblem(Project project) {
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
PsiClass cls = facade.findClass("A", GlobalSearchScope.projectScope(project));
System.out.println("cls.getName() = " + cls.getName());
PsiField f = cls.findFieldByName("l", false);
System.out.println("f.getType().getCanonicalText() = " + f.getType().getCanonicalText());
}
public static void setupJdk(Project project) {
Sdk jdk = JavaSdk.getInstance().createJdk("java 1.8", jdkHomeDirectory(), false);
ProjectJdkTable.getInstance().addJdk(jdk);
ProjectRootManager.getInstance(project).setProjectSdk(jdk);
NewProjectUtil.applyJdkToProject(project, jdk);
Module[] modules = ModuleManager.getInstance(project).getModules();
for (Module module : modules) {
ModuleRootModificationUtil.setModuleSdk(module, jdk);
}
}
private static String jdkHomeDirectory() {
return "/usr/lib/jvm/jdk1.8.0_181";
}
private static String root() {
return "/tmp/projectRoot";
}
private static String srcRoot() {
return root() + "/src";
}
private static String moduleIMLPath() {
return root() + "/file.iml";
}
}
请先登录再写评论。