Sasha Shpota
Sasha Shpota

Reputation: 10290

IntelliJ Plugin Development: how to make class extend another class

I'm implementing a plugin in which I need to add extends clause for an existing class.

I have PsiClass instance representing say MyClass.

There is an API that allows to get all the classes that MyClass extends:

PsiReferenceList extendsList = psiClass.getExtendsList()

And theoretically I can add something to it and that will work.

Problem: PsiReferenceList.add() consumes PsiElement and I don't know how to create an object of PsiElement having fully qualified name of the class I want to use.

More specifically, how to transform string com.mycompany.MyAbstractClass to PsiElement representing this class?

Update: I managed to achieve the result using the following logic:

PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
PsiReferenceList extendsList = aClass.getExtendsList();
PsiShortNamesCache instance = PsiShortNamesCache.getInstance(project);
PsiClass[] abstractClasses = instance.getClassesByName(
        "MyAbstractClass", 
        GlobalSearchScope.allScope(project)
);
PsiJavaCodeReferenceElement referenceElement = factory
        .createClassReferenceElement(abstractClasses[0]);
extendsList.add(referenceElement);

It works but I guess there should be more optimal way.

Upvotes: 1

Views: 747

Answers (1)

ice1000
ice1000

Reputation: 6569

You can make a String which is the code you want to generate, like

String code = "class A extends B { }"

Then, use this code to convert text into PsiElement:

PsiElement fromText(String code, Project project) {
  return PsiFileFactory
        .getInstance(project)
        .createFileFromText(JavaLanguage.INSTANCE, code)
        .getFirstChild()
}

And you'll get the corresponding PsiElement.

Then, myClass.replace(fromText(code)).

BTW you can also do classNamePsiElement.addAfter(fromText("extends Xxx")) which is considered more efficient.

Upvotes: 1

Related Questions