My first intention: Please take a look at it...
I started to create a new intention. It is working now - but I feel that I have missed the best way, especially when replacing the code ;).
Could you please show me, how to solve this problem "in the right way"?
Thanks
/*
Copyright (c) 2005 Your Corporation. All Rights Reserved.
*/
package de.xore.plugins.idea.renaming;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiReturnStatement;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
/**
<p/>
Date: 08.03.2005<br> Time: 23:42:12<br>
*
@author <a href="http://johannes-schneider.info">Johannes Schneider</a> - <a href="http://www.xore.de">Xore
Systems</a>
*/
public class CollectionsWrapperIntention implements IntentionAction {
public String getText() {
return "Wrap collection";
}
public String getFamilyName() {
return "---WrapCollectionsFamily";
}
public boolean isAvailable( Project project, Editor editor, PsiFile file ) {
if ( !( file instanceof PsiJavaFile ) ) {
return false;
}
try {
PsiJavaFile javaFile = ( PsiJavaFile ) file;
PsiElement actualElement = javaFile.findElementAt( editor.getCaretModel().getOffset() );
PsiReturnStatement returnStatement = ( PsiReturnStatement ) PsiTreeUtil.getParentOfType( actualElement, PsiReturnStatement.class );
PsiMethod psiMethod = ( PsiMethod ) PsiTreeUtil.getParentOfType( actualElement, PsiMethod.class );
PsiReferenceExpression returnReference = ( PsiReferenceExpression ) PsiTreeUtil.getChildOfType( returnStatement, PsiReferenceExpression.class );
PsiManager manager = actualElement.getManager();
PsiClassType listType = manager.getElementFactory().createTypeByFQClassName( "java.util.List", actualElement.getResolveScope() );
if ( !listType.isAssignableFrom( returnReference.getType() ) ) {
return false;
}
if ( !psiMethod.getName().equalsIgnoreCase( "get" + returnReference.getText() ) ) {
return false;
}
} catch ( Throwable e ) {
return false;
}
return true;
}
public void invoke( Project project, Editor editor, PsiFile file ) throws IncorrectOperationException {
PsiJavaFile javaFile = ( PsiJavaFile ) file;
PsiElement actualElement = javaFile.findElementAt( editor.getCaretModel().getOffset() );
PsiReturnStatement returnStatement = ( PsiReturnStatement ) PsiTreeUtil.getParentOfType( actualElement, PsiReturnStatement.class );
PsiReferenceExpression returnReference = ( PsiReferenceExpression ) PsiTreeUtil.getChildOfType( returnStatement, PsiReferenceExpression.class );
int offset = returnReference.getTextOffset();
int length = returnReference.getTextLength();
editor.getDocument().replaceString( offset, offset + length, "Collections.unmodifiableList(" + returnReference.getText() + ")" );
}
public boolean startInWriteAction() {
return true;
}
}
Please sign in to leave a comment.
Johannes Schneider wrote:
You can do something like this instead (untested):
PsiManager mgr = PsiManager.getInstance(editor.getProject());
PsiElement e = mgr.getElementFactory.createExpressionFromText("Collections.unmodifiableList(" + returnReference.getText() + ")",
returnReference.getContext());
mgr.getCodeStyleManager().reformat(returnReference.replace(e));
Didn't look too closely at the rest of your code, but it seemed fine so far.
HTH,
Sascha
Thank you for your answer - I'll change that.
Just one more question.
I would like to add an import statement for java.util.Collections if necessary.
How can that be done?
Johannes Schneider wrote:
Use "java.util.Collections" in the createExpressionFromText()-call and change the code to
e = returnReference.replace(e);
mgr.getCodeStyleManager().shortenClassReferences(e);
mgr.getCodeStyleManager().reformat(e);
HTH,
Sascha
Thank you ;).
Sorry for posting again - but I have one more problem...
The next step is wrapping the "setter".
The problem is, that I have to add a second expression. But I am not able to add a semicolon...
PsiAssignmentExpression assignExpr = ( PsiAssignmentExpression ) PsiTreeUtil.getParentOfType( actualElement, PsiAssignmentExpression.class );
PsiMethod method = ( PsiMethod ) PsiTreeUtil.getParentOfType( actualElement, PsiMethod.class );
PsiExpression clearExpression = manager.getElementFactory().createExpressionFromText( assignExpr.getLExpression().getText() + ".clear()", method.getContext() );
PsiExpression addAllExpression = manager.getElementFactory().createExpressionFromText( assignExpr.getLExpression().getText() + ".addAll(" + assignExpr.getRExpression().getText() + ")", method.getContext() );
PsiElement changedExpression = assignExpr.replace( clearExpression );
changedExpression.getParent().addAfter( addAllExpression, changedExpression );
manager.getCodeStyleManager().reformat( method );
This adds the second statement - but without a semicolon...
Okay - found it ;)
Just use "Statements" instead of "Expressions"
PsiStatement clearStatement = manager.getElementFactory().createStatementFromText( assignExpr.getLExpression().getText() + ".clear();", method.getContext() );
PsiStatement addAllStatement = manager.getElementFactory().createStatementFromText( assignExpr.getLExpression().getText() + ".addAll(" + assignExpr.getRExpression().getText() + ");", method.getContext() );
PsiElement changedExpression = assignStatement.replace( clearStatement );
changedExpression.getParent().addAfter( addAllStatement, changedExpression );
manager.getCodeStyleManager().reformat( method );