How to change PSIClass (java files) ?

 Hello,

I am trying to parse some java code and modify some of it's contents (method names, variable types) and currently I can iterate through all .java files on the project folder but now I can't change the text content of the PSI Class referring to the .java file since there is no setText() method in the PsiClass class. Here is my current code:

// Translation will be made here
Processor<PsiClass> processor = new Processor<PsiClass>() {
@Override
public boolean process(PsiClass psiClass) {
// Do work here
System.out.println(psiClass.getText());
return true;
}
};

// Get all JavaClasses on project folder
AllClassesGetter.processJavaClasses(
new PlainPrefixMatcher(""),
project,
GlobalSearchScope.projectScope(project),
processor
);
0
48 comments
Avatar
Permanently deleted user

I did as you said and it worked but I have a small problem that I can't fix when I add the ImportStatement (code below). 

public void addPackage(PsiJavaFile javaFile,Project project){
//Adds package name
String newPackage = "org.onepf.oms";
PsiPackageStatement newStatement;
newStatement = JavaPsiFacade.getElementFactory(project).createPackageStatement(newPackage);
PsiImportStatement[] list= javaFile.getImportList().getImportStatements();
int firstPosition = 0 ;

PsiImportStatement firstImport = list[firstPosition];
javaFile.addBefore(newStatement,firstImport); (ERROR here also -> Assertion failed: anchorBefore == null || anchorBefore.getTreeParent() == parent
java.lang.Throwable)
}

The only problem is that the result I get is the import and the package on the same line like this:


package org.onepf.oms;import com.intellij.codeInsight.completion.AllClassesGetter;

 

Any idea on how to fix this? ( I tried adding "/n" to the package name but since the ";" is applied after by the createPackageStatement method it won't work)

0

Have you tried PsiJavaFile#setPackageName, is it better?

0
Avatar
Permanently deleted user

Yes, it worked if I kept using  the Runnable  object. Thank you for your help!

0
Avatar
Permanently deleted user

When iterating through the file methods and fields, if I change one of them like this:

public void addField(PsiJavaFile javaFile, Project project,PsiField field){
String newFieldValue="IOpenInAppBillingService mService;";
PsiField newField;
newField = JavaPsiFacade.getElementFactory(project).createFieldFromText(newFieldValue,javaFile);
field.replace(newField);
}

I end up having this error:

java.lang.AssertionError: Next sibling of the element 'PsiField:mService' changed. Was: PsiWhiteSpace; Now:null; Root:PsiClass:TextBoxes

Any idea on how to avoid this?

0

It'd be easier to answer if you quoted both the exception message and the stack trace. I suspect that you get this from recursive visitor internals. The fix is to do the change not inside the visitor, but use it only to accumulate all elements you need to change, and then modify them after traversing the PSI.

0
Avatar
Permanently deleted user

It makes a lot of sense, I will try to save all elements to be changed and only modify them after the iteration.

0
Avatar
Permanently deleted user

I am trying to change a method's body but I get this error while running the plugin:

file/doc text length different, File[PsiJavaFile:IabHelper.java IabHelper.java, Language: JAVA, SingleRootFileViewProvider{myVirtualFile=file:///home/guilhermeandraade/Desktop/android-play-billing-master/TrivialDrive/app/src/main/java/com/example/android/trivialdrivesample/util/IabHelper.java, content=com.intellij.psi.SingleRootFileViewProvider$PsiFileContent@100927be}] file.length=50042; doc.length=50046
java.lang.Throwable
at com.intellij.openapi.diagnostic.Logger.error(Logger.java:127)
at com.intellij.psi.formatter.FormattingDocumentModelImpl.checkDocument(FormattingDocumentModelImpl.java:75)
at com.intellij.psi.formatter.FormattingDocumentModelImpl.createOn(FormattingDocumentModelImpl.java:65)
at com.intellij.lang.java.JavaFormattingModelBuilder.createModel(JavaFormattingModelBuilder.java:58)
at com.intellij.formatting.CoreFormatterUtil.buildModel(CoreFormatterUtil.java:48)
at com.intellij.psi.impl.source.codeStyle.CodeFormatterFacade.processText(CodeFormatterFacade.java:236)
at com.intellij.psi.impl.source.PostprocessReformattingAspect$ReformatRangesAction.execute(PostprocessReformattingAspect.java:730)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.doPostponedFormattingInner(PostprocessReformattingAspect.java:338)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.lambda$null$4(PostprocessReformattingAspect.java:245)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.lambda$disablePostprocessFormattingInside$0(PostprocessReformattingAspect.java:113)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.disablePostprocessFormattingInside(PostprocessReformattingAspect.java:121)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.disablePostprocessFormattingInside(PostprocessReformattingAspect.java:112)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.lambda$postponedFormattingImpl$5(PostprocessReformattingAspect.java:245)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:450)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:54)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeNonCancelableSection(CoreProgressManager.java:198)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.atomic(PostprocessReformattingAspect.java:166)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.postponedFormattingImpl(PostprocessReformattingAspect.java:241)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.doPostponedFormatting(PostprocessReformattingAspect.java:237)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.lambda$doPostponedFormatting$3(PostprocessReformattingAspect.java:220)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:494)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:443)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:54)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeNonCancelableSection(CoreProgressManager.java:198)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.atomic(PostprocessReformattingAspect.java:166)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.doPostponedFormatting(PostprocessReformattingAspect.java:215)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.decrementPostponedCounter(PostprocessReformattingAspect.java:157)
at com.intellij.psi.impl.source.PostprocessReformattingAspect.access$300(PostprocessReformattingAspect.java:62)
at com.intellij.psi.impl.source.PostprocessReformattingAspect$2.writeActionFinished(PostprocessReformattingAspect.java:103)
at sun.reflect.GeneratedMethodAccessor23.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.util.EventDispatcher.dispatch(EventDispatcher.java:99)
at com.intellij.util.EventDispatcher.access$200(EventDispatcher.java:35)
at com.intellij.util.EventDispatcher$2.invoke(EventDispatcher.java:79)
at com.sun.proxy.$Proxy5.writeActionFinished(Unknown Source)
at com.intellij.openapi.application.impl.ApplicationImpl.fireWriteActionFinished(ApplicationImpl.java:1261)
at com.intellij.openapi.application.impl.ApplicationImpl.endWrite(ApplicationImpl.java:1112)
at com.intellij.openapi.application.impl.ApplicationImpl.access$600(ApplicationImpl.java:93)
at com.intellij.openapi.application.impl.ApplicationImpl$WriteAccessToken.finish(ApplicationImpl.java:1145)
at com.intellij.openapi.command.WriteCommandAction$2.run(WriteCommandAction.java:117)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:129)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:100)
at com.intellij.openapi.command.WriteCommandAction.performWriteCommandAction(WriteCommandAction.java:108)
at com.intellij.openapi.command.WriteCommandAction.execute(WriteCommandAction.java:83)
at com.intellij.openapi.command.WriteCommandAction.runWriteCommandAction(WriteCommandAction.java:187)
at com.intellij.openapi.command.WriteCommandAction.runWriteCommandAction(WriteCommandAction.java:174)
at TextBoxes.changeMethod(TextBoxes.java:171)
at TextBoxes.changeElements(TextBoxes.java:120)
at TextBoxes.actionPerformed(TextBoxes.java:110)

Here is the code that gets the error:

public void changeMethod(PsiJavaFile javaFile, Project project,PsiMethod method){
Runnable modificationRunnable= createMethodRunnable(javaFile,project,method);
WriteCommandAction.runWriteCommandAction(project, modificationRunnable);

}

Any idea on how to fix this error?

0

Is it the very first exception in the idea.log? (Help | Show log)

If not, please attach the first one. If yes, then it looks like IDEA found itself in an inconsistent state (which shouldn't happen), and it should have reported it with another exception earlier. I'd gladly debug that, but I'd need the full code of the plugin.

0
Avatar
Permanently deleted user

How can I send you the code then? I think it will be easier because it seems a deep bug.

0

You can zip it, upload to some storage and provide a link. You can also upload it to http://uploads.jetbrains.com/

0
Avatar
Permanently deleted user

After fixing the problem, my plugin just stopped working both in debug as in production!  How can I attach zip's here? It only gives me the possibility to attach images.

0

Sorry, I've discovered that myself and edited my previous comment.

0
Avatar
Permanently deleted user

 Here is the link : https://www.dropbox.com/sh/5qpf34nv3qlez30/AAChNrjIe6OTmVzHL_h-nbbIa?dl=0

android-play-billing-master is the project to test the plugin and openIabTranslator is the plugin code.

Tell me if you can reach the same error,

Thank you.

PS: I thing upgrading IntelliJ IDEA to the newest version messed up the plugin, it doesn't find Java classes anymore so it does nothing at all. 

0

Does File | Invalidate Caches and restart help with the "doesn't find Java classes anymore" issue?

I've reproduced the exception. Did you check the log and see another exception before it? Please always use \n in PSI text, IDEA manages line separators itself.

ERROR: Wrong line separators: '\n \r\nserviceI...' at offset 9
java.lang.Throwable
at com.intellij.openapi.diagnostic.Logger.error(Logger.java:132)
at com.intellij.openapi.util.text.StringUtil.assertValidSeparators(StringUtil.java:2679)
at com.intellij.openapi.editor.impl.DocumentImpl.assertValidSeparators(DocumentImpl.java:618)
at com.intellij.openapi.editor.impl.DocumentImpl.replaceString(DocumentImpl.java:544)
at com.intellij.openapi.editor.impl.DocumentImpl.replaceString(DocumentImpl.java:537)
at com.intellij.psi.impl.PsiToDocumentSynchronizer.doCommitTransaction(PsiToDocumentSynchronizer.java:285)
at com.intellij.psi.impl.PsiToDocumentSynchronizer.access$300(PsiToDocumentSynchronizer.java:42)
at com.intellij.psi.impl.PsiToDocumentSynchronizer$6.syncDocument(PsiToDocumentSynchronizer.java:266)
at com.intellij.psi.impl.PsiToDocumentSynchronizer$1.run(PsiToDocumentSynchronizer.java:107)
at com.intellij.psi.impl.PsiToDocumentSynchronizer.performAtomically(PsiToDocumentSynchronizer.java:126)
at com.intellij.psi.impl.PsiToDocumentSynchronizer.doSync(PsiToDocumentSynchronizer.java:104)
at com.intellij.psi.impl.PsiToDocumentSynchronizer.commitTransaction(PsiToDocumentSynchronizer.java:263)
at com.intellij.pom.core.impl.PomModelImpl.commitTransaction(PomModelImpl.java:250)
at com.intellij.pom.core.impl.PomModelImpl.runTransaction(PomModelImpl.java:206)
at com.intellij.psi.impl.source.tree.ChangeUtil.prepareAndRunChangeAction(ChangeUtil.java:167)
at com.intellij.psi.impl.source.tree.CompositeElement.replaceChild(CompositeElement.java:699)
at com.intellij.psi.impl.source.codeStyle.CodeEditUtil.replaceChild(CodeEditUtil.java:204)
at com.intellij.psi.impl.source.tree.CompositeElement.replaceChildInternal(CompositeElement.java:542)
at com.intellij.psi.impl.source.tree.SharedImplUtil.doReplace(SharedImplUtil.java:211)
at com.intellij.psi.impl.source.tree.LazyParseablePsiElement.replace(LazyParseablePsiElement.java:240)

0
Avatar
Permanently deleted user

I fixed that and removed the "\r" on the String newSetPackage but the plugin only seems to work one time, if I run it again it doesn't work anymore.. Can you re-run the plugin with the fix and see if IabHelper.java on java.utils is modified ?

0

BTW it's strongly discouraged to save PSI in long-living fields. AnAction instances are created just once, so your collection fields are never cleared, and likely contain invalid PSI when invoked second time.

0
Avatar
Permanently deleted user

Do you recommend resetting the fields at the end?

PS: Still getting the problem while iterating over the java classes, it finds the project folder but 

AllClassesGetter.processJavaClasses(
new PlainPrefixMatcher(""),
project,
GlobalSearchScope.projectScope(project),
processor
);

doesn't find anything so the plugin will end with no modifications at all. 

0

Please sign in to leave a comment.