PsiType from java generic string

I've been looking for an example how to create a PsiType or PsiClass from a string representation of a generic class.
I have a plugin that generates PsiMethods and inserts them into the current class in the editor.
The dialog in the plugin allows the user to type a list of arguments to be used by the PsiMethod
The arguments are used to build the algorithms generated by the plugin.

Arguments:  Integer arg1, List<String> arg2, UserGenericType<UserClass> arg3

I can parse the non-generic argument types using:

JavaPsiFacade.getInstance(project).findClass(nonGenericClassName, projectScope)

however, I can't find examples on how to create the generic class definitions.

It looks like I may be able to do it by getting the generic class without type parameters:

JavaPsiFacade.getInstance(project).findClass("java.util.List", projectScope)

and replacing the generic parameter using the class substituter

TypeConversionUtil.getClassSubstitutor(classPtr, elementClass, result.getSubstitutor())

Or maybe use the type creator to create a new type from the string:

JavaPsiFacade.getInstance(project).getElementFactory().createTypeFromText("java.util.List<java.lang.String>", null)

Any help would be greatly appreciated.

2 comments
Comment actions Permalink

After more digging and searching though grepcode, I've got a solution.
It looks like a PsiClass can't hold generic information (List<String>) but a PsiType can.

I tried using

JavaPsiFacade.getInstance(project).getElementFactory().createTypeByFQClassName("javaj.util.List<java.lang.String>")

but it didn't return a type I could use.

Here's a simple example how I plan to handle creating a PsiType from a string description of a generic (Like List<String>)

public PsiType buildGenericType(String name) {
int index = name.indexOf("<");
String genericName = name.substring(0, index).trim();
String elementName = name.substring(index + 1, name.indexOf(">")).trim();
if (genericName.equals("List")) genericName = "java.util.List";
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
PsiElementFactory factory = facade.getElementFactory();
GlobalSearchScope globalsearchscope = GlobalSearchScope.allScope(project);
PsiClass genericClass = facade.findClass(genericName, globalsearchscope);
PsiType elementType =  factory.createType(facade.findClass(elementName, globalsearchscope));
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY.putAll(genericClass, new PsiType[] { elementType });
return JavaPsiFacade.getElementFactory(project).createType(genericClass, substitutor);
}
If anyone knows of a better way to do this, let me know

4

Please sign in to leave a comment.